Home > Blockchain >  Ansible. Parse yaml
Ansible. Parse yaml

Time:12-01

I'm trying to get the address 192.168.176.129 from a variable interf:

"interf": {
    "1": {
        "adminstatus": "up",
        "description": "",
        "ifindex": "1",
        "ipv4": [
            {
                "address": "192.168.176.129",
                "netmask": "255.255.255.0"
            }
        ],
        "mac": "000c29788c7f",
        "mtu": "1500",
        "name": "ether1",
        "operstatus": "up",
        "speed": "1000000000"
    }
}

I tried to do this, but nothing comes out

- set_fact:
    test_name: "{{ interf|
                   select('regex', my_regex)|
                   first|
                   regex_replace(my_regex, my_replace) }}"
  vars:
    my_regex: '^address (.*)$'
    my_replace: '\1'
- debug:
    var: test_name

How do I get the address value: 192.168.176.129 and the operstatus value: up? What am I doing wrong?

CodePudding user response:

Why using a regex? Ansible is capable of accessing JSON and YAML properties of dictionaries as well as accessing lists.

If you only care about one IP address, you can do:

- debug:
   var: interf['1'].ipv4.0.address

If you care about the possibility to have multiple addresses, then you'll get a list of addresses with:

- debug:
   var: interf['1'].ipv4 | map(attribute='address')

Given the playbook:

- hosts: localhost
  gather_facts: no
  vars:
        interf:
          '1':
            adminstatus: up
            description: ''
            ifindex: '1'
            ipv4:
            - address: 192.168.176.129
              netmask: 255.255.255.0
            mac: 000c29788c7f
            mtu: '1500'
            name: ether1
            operstatus: up
            speed: '1000000000'

  tasks:
    - name: Get the first IP address only
      debug:
       var: interf['1'].ipv4.0.address

    - name: Get a list of (possibly) all the IPs address
      debug:
       var: interf['1'].ipv4 | map(attribute='address')

This yields:

TASK [Get the first IP address only] **************************************************
ok: [localhost] => 
  interf['1'].ipv4.0.address: 192.168.176.129

TASK [Get a list of (possibly) all the IPs address] ***********************************
ok: [localhost] => 
  interf['1'].ipv4 | map(attribute='address'):
  - 192.168.176.129

CodePudding user response:

I took a slightly different approach assuming that the var is being parsed as a JSON object and not directly converted to YAML.

In this example, we parse the JSON first then use JMESPATH to extract the addresses. The debug statement loops through the list and outputs each address.

If you know that you'll only ever need the first item, then you can change the json query to interf.*.ipv4[*].address | [0][0] and only the one address is returned.

- name: Test
  hosts: localhost
  vars:
    json: | 
      {
        "interf": {
          "1": {
              "adminstatus": "up",
              "description": "",
              "ifindex": "1",
              "ipv4": [
                  {
                      "address": "192.168.176.129",
                      "netmask": "255.255.255.0"
                  }
              ],
              "mac": "000c29788c7f",
              "mtu": "1500",
              "name": "ether1",
              "operstatus": "up",
              "speed": "1000000000"
          }
        }
      }
  tasks:
    - name: Extract IPs
      set_fact: 
        addresses: "{{ json | from_json | json_query(\"interf.*.ipv4[*].address | [0]\") | list }}"
    - name: Loop through addresses
      debug:
        msg: "{{ item }}"
      with_items: "{{ addresses }}"
  • Related