Saturday, August 31, 2019

Formatting numbers in your Ansible/Jinja templates


Quite often you may have to use an index somewhere in your templates. I think the most common scenarion is to track the loop index within a for loop in Jinja2 or a loop in Ansible.

One such scenario is shown below, where I'm trying to produce the configuration for the uplink ports of a router. Notice that I'm using the index variable to differentiate the configuration sections of each port and store it in a different file.

  - name: Generate uplink ports config 
    template:
      src: configtemplates/{{ ansible_network_os }}/uplink_ports_cfg
      dest: deviceconfigs/{{ inventory_hostname }}/{{ index }}_uplink_ports_cfg
    delegate_to: localhost
    changed_when: false
    loop: "{{ uplink_ports }}"
    loop_control:
      index_var: index
    when: uplink_ports is defined

The filenames produced by this task are in the following format
   0_downlink_ports_cfg
   1_downlink_ports_cfg
   2_downlink_ports_cfg
   ..
   8_downlink_ports_cfg
   9_downlink_ports_cfg
  10_downlink_ports_cfg

After producing the config sections I'll use the 'assemble' function in Ansible, to merge all the sections in a common file. I expect the merging to follow the index sequence, which is the default behavior of the 'assemble' module, based on filename sorting.

And everything works well, as long as the index is smaller than 10. If you exceed 10, then the sorting function of 'assemble' will mess up, by merging the 10th section before the 2nd.

In this case you can start indexing with a two digit number and thank god there's an easy way to do that. Just replace  '{{ index }}' with '{{ "%02d"|format(index) }}'.

The filenames produced in this case are in the following format and 'assemble' merges correctly.

  00_downlink_ports_cfg
  01_downlink_ports_cfg
  02_downlink_ports_cfg
   ..
  08_downlink_ports_cfg
  09_downlink_ports_cfg
  10_downlink_ports_cfg

No comments:

Post a Comment