Search code examples
jsonansiblejmespath

Ansible reading nested json values and matching variable


I am using this in an Ansible playbook:

- name: Gather info from Vcenter
  vmware_vm_info:
    hostname: "{{ result_item.vcenter }}"
    username: "{{ ansible_username }}"
    password: "{{ ansible_password }}"
    validate_certs: no
  register: vminfo
  loop: "{{ result.list }}"
  loop_control:
    loop_var: result_item

I loop through a csv which has a list of VMs and their Vcenters. The json output from the Ansible task is this:

{
  "results": [
    {
      "changed": false,
      "virtual_machines": [
        {
          "guest_name": "Server1",
          "guest_fullname": "SUSE Linux Enterprise 11 (64-bit)",
          "power_state": "poweredOn",
          },
        {
          "guest_name": "Server2",
          "guest_fullname": "FreeBSD Pre-11 versions (64-bit)",
          "power_state": "poweredOn",
        },

Now I need to query this output for the VMs in my csv (guest_name matches vmname) and use set_fact to indicate whether the VMs in the csv are poweredOff or poweredOn. Next I can use it as a conditional on whether to power off the VM or not based on its current status.

I can't seem to get the json_query to work when matching to the VM name in the csv to the json output and then getting the corresponding power status. Any ideas?

CSV file:

vmname    vcenter  
Server1   Vcenter1  
Server2   Vcenter1

Solution

  • Q: "set_fact to indicate whether the VMs in the CSV are powered off or powered on."

    A: For example

        - read_csv:
            path: servers.csv
            dialect: excel-tab
          register: result
        - set_fact:
            servers: "{{ result.list|map(attribute='vmname')|list }}"
        - set_fact:
            virtual_machines: "{{ virtual_machines|default([]) +
                                  [dict(_servers|zip(_values))] }}"
          loop: "{{ vminfo.results }}"
          vars:
            _servers: "{{ servers|intersect(_dict.keys()|list) }}"
            _values: "{{ _servers|map('extract',_dict)|list }}"
            _dict: "{{ item.virtual_machines|
                       items2dict(key_name='guest_name', value_name='power_state') }}"
        - debug:
            var: virtual_machines
    

    gives

      virtual_machines:
      - Server1: poweredOn
        Server2: poweredOn
    

    Servers missing in the vminfo.results will be silently ignored.


    Q: "Use it as a conditional on whether to power off the VM or not."

    A: For example Server1 in the first host

        - debug:
            msg: "Host={{ _host }} VM={{ _vm }} is poweredOn"
          when: virtual_machines[_host][_vm] == 'poweredOn'
          vars:
            _host: 0
            _vm: Server1
    

    gives

      msg: Host=0 VM=Server1 is poweredOn