Search code examples
mongodbansibleansible-inventory

How do I access variables of a host using dynamic inventory in a MongoDB database using Ansible playbook?


I am trying to generate initial configurations using information stored in MongoDB. I am using the dynamic inventory feature with Ansible. The backend is a simple mongodb database. When manually running ansible_fetch_mongodb.py --list, it returns groups and their variables/children in JSON as per Ansible's requirements. Using the --host <hostname> argument also returns hosts and their variables with no issues. However, when trying to access the variables, say item.hostname, or item.var2 within an Ansible playbook, it errors out and tells me that item.hostname isn't defined. I'm using ansible-playbook build_configs.yml -v -i ansible_fetch_mongodb.py command to run it all. I have been working for hours on this issue and any help with proper syntax to access variables from a dynamic source is very appreciated.

Here is the playbook:

- hosts: localhost 
  tasks:
  - name: configuration generator 
    template: 
      src=roles/core_router/templates/3850.j2
      dest=/etc/ansible/generated_templates/{{ item }}.txt
    with_inventory_hostnames: all
  - debug: msg="{{ item.data1_svi_ip }}"
    with_inventory_hostnames: all

Here is the host represented in MongoDB:

{
    "_id": "ROUTER123",
    "hostname": "ROUTER123",
    "vars": {
        "data1_svi_ip": "10.19.83.254 255.255.254.0",
        "device_num": "01",
        "device_type": "Router",
        "floor": "04",
        "grp_ip": "10.19.93.14 255.255.255.240",
        "mgmt_net": "10.19.103.254 255.255.254.0",
        "model": "3850",
    }
}

Here are the groups represented in MongoDB:

{
    "_id": "Router",
    "children": [],
    "hosts": [
        "Router123",
    ],
    "name": "Router",
    "vars": {}
}

Here is the error:

TASK [debug] ****************************************************************************************************************************************************************

fatal: [localhost]: FAILED! => {"failed": true, "msg": "the field 'args' has an invalid value, which appears to include a variable that is undefined. The error was: 'ansible.vars.unsafe_proxy.AnsibleUnsafeText object' has no attribute 'data1_svi_ip'\n\nThe error appears to have been in '/etc/ansible/build_configs.yml': line 8, column 5, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n with_inventory_hostnames: all\n - debug: msg=\"{{ item.data1_svi_ip }}\"\n ^ here\nWe could be wrong, but this one looks like it might be an issue with\nmissing quotes. Always quote template expression brackets when they\nstart a value. For instance:\n\n with_items:\n - {{ foo }}\n\nShould be written as:\n\n with_items:\n - \"{{ foo }}\"\n"}


Solution

  • with_inventory_hostnames lookup plugin returns the names of the hosts. They are strings, not objects, so Ansible reports: no attribute 'data1_svi_ip'.

    To access host variables, you need to use:

    - debug:
        var: hostvars[item].data1_svi_ip
      with_inventory_hostnames: all