yaobin.wen

Yaobin's Blog

View on GitHub
6 January 2022

Ansible: Add elements to list

by yaobin.wen

Today, I needed to convert the following list config_original

config_original:
  - iface: "enx00e07cc85b6e"
    subnet: "192.168.16.0/24"
    netmask: "255.255.255.0"
    listen: "192.168.16.30"
    range:
      start: "192.168.16.1"
      end: "192.168.16.28"
    reserved:
      - "192.168.16.29"
  - iface: "enx241b7af8cdf1"
    subnet: "192.168.16.0/24"
    netmask: "255.255.255.0"
    listen: "192.168.16.60"
    range:
      start: "192.168.16.31"
      end: "192.168.16.58"
    reserved:
      - "192.168.16.59"

into the list config_modified as follows:

config_modified:
  - iface: "enx00e07cc85b6e"
    dhcp: off
    subnet: "192.168.16.0/24"
    netmask: "255.255.255.0"
    static_ip_addresses:
      - "192.168.16.29"
    gateway: "192.168.16.1"
  - iface: "enx241b7af8cdf1"
    dhcp: off
    subnet: "192.168.16.0/24"
    netmask: "255.255.255.0"
    static_ip_addresses:
      - "192.168.16.59"
    gateway: "192.168.16.31"

Basically, for every entry in config_original, I needed to:

I examined the following filters:

But none of them worked for me. JSONPath (as explained in JSONPath - XPath for JSON) looks promising initially but:

[
  "enx00e07cc85b6e",
  "192.168.16.0/24",
  "enx241b7af8cdf1",
  "192.168.16.0/24"
]

Inspired by [1] and [2], I figured out the following playbook to do the conversion:

- name: Demo how to add elements to a list.
  gather_facts: no
  hosts: all
  tasks:
    - name: Define the original data.
      set_fact:
        config_original:
          - iface: "enx00e07cc85b6e"
            subnet: "192.168.16.0/24"
            netmask: "255.255.255.0"
            listen: "192.168.16.30"
            range:
            start: "192.168.16.1"
            end: "192.168.16.28"
            reserved:
              - "192.168.16.29"
          - iface: "enx241b7af8cdf1"
            subnet: "192.168.16.0/24"
            netmask: "255.255.255.0"
            listen: "192.168.16.60"
            range:
            start: "192.168.16.31"
            end: "192.168.16.58"
            reserved:
              - "192.168.16.59"

    - name: Transform config_original to config_modified
      vars:
        config_modified: []
        config_entry:
          # `item` is re-evaluated in every iteration of the loop.
          iface: "{ {item.iface} }"
          dhcp: off
          subnet: "{ {item.subnet} }"
          netmask: "{ {item.netmask} }"
          static_ip_address: "{ {item.reserved} }"
          gateway: ~
      set_fact:
          config_modified: "{ {config_modified + [config_entry]} }"
      loop: "{ {config_original} }"

    - name: Display the final result.
      debug:
        var: config_modified

There are a few notes about the implementation:

The output of the debug task confirms the modification:

TASK [Display the final result.] ********************************
ok: [localhost] => 
  config_modified:
  - dhcp: false
    gateway: null
    iface: enx00e07cc85b6e
    netmask: 255.255.255.0
    static_ip_address:
    - 192.168.16.29
    subnet: 192.168.16.0/24
  - dhcp: false
    gateway: null
    iface: enx241b7af8cdf1
    netmask: 255.255.255.0
    static_ip_address:
    - 192.168.16.59
    subnet: 192.168.16.0/24

References:

Tags: Tech