ansiblejinja2ansible-inventory

Ansible passing variables to j2 templates


With ansible I am using j2 templates to replace files, and pass through environment vars unique to each environment and some shared. Neither the variables for global or local work. I have the following set-up and structure.

The directory structure

project
├── inventory.ini
├── playbooks
│   ├── do-something.yaml
│   └── template
│       └── myfile.json.j2
└── vars
    └── config_vars.yaml

Inventory file

inventory.ini

[myhosts]
host1 ansible_host=192.168.1.10

Config Vars file

# vars/config_vars.yaml

all:
  vars:
    my_value_one: "value1"
  children:
    myhosts:
      hosts:
        host1:
          my_value_two: "value2"

Playbook file

# playbooks/do-something.yaml

---
- name: Configure Nodes
  hosts: myhosts
  become: yes
  vars_files:
    - ../vars/config_vars.yml
  tasks:
    - name: Replace file with j2 template
      template:
        src: templates/myfile.json.j2
        dest: /home/{{ ansible_user }}/my-folder/myfile.json

j2 template file

# templates/myfile.json.j2

{
  "value_one": "{{ my_value_one }}",
  "value_two": "{{ my_value_two }}",
}

Ansible Version: 2.16.7 Jinja: 3.1.4

I have tried the following:-


Solution

  • Changing directory structure

    Playing with inventory, changes structure, using yaml file

    You didn't specify what exactly you tried to change but the core reason is that the role structure is not the same as the project structure - the latter does not use the vars folder.

    You are expecting your variables from ../vars/config_vars.yml to be loaded as the inventory variables but they are not. Moreover, your ../vars/config_vars.yml is itself the inventory file written in YAML format but you're loading it as the variable file. So, for example, to use that my_value_two you would need to refer to all.children.myhosts.hosts.host1.my_value_two - which is anything but what should be done in Ansible.

    To benefit from the built-in features and pick up the variables automatically instead of loading them via vars_files you can follow the recommended project structures and do some of the following things:

    Consider an example for the last option:

    # inventories/my_hosts.yaml
    ---
    all:
      vars:
        my_value_one: "value1"
      children:
        myhosts:
          hosts:
            host1:
              ansible_host: 192.168.1.10
              my_value_two: "value2"
    

    Now, once you remove the vars_files from your playbook this is enough to get what you want with the below command (split to multiple lines to make it readable without scrolling):

    ansible-playbook playbooks/do-something.yaml \
      --inventory inventories/my_hosts.yaml
    

    If you want to store the variables in the folders instead, you have multiple options covered by the documentation. Let's consider just one of them:

    # inventories/my_hosts/group_vars/all.yaml
    ---
    my_value_one: "value1"
    
    # inventories/my_hosts/host_vars/host1.yaml
    ---
    my_value_two: "value2"          
    
    # inventories/my_hosts/inventory.yaml
    ---
    all:
      children:
        myhosts:
          hosts:
            host1:
              ansible_host: 192.168.1.10
    

    The equivalent command could look like this:

    ansible-playbook playbooks/do-something.yaml \
      --inventory inventories/my_hosts