Load ansible vars in specific tasks

I feel I must be missing this answer as it seems obvious but I've read a number of posts and have not been able to get this working.

Currently I am loading and then templating vars from files depending on inventory hostnames, like so:

  - name: load unique dev vars from file
    include_vars:
      file: ~/ansible/env-dev.yml
    when: inventory_hostname in groups[ 'devs' ]

  - name: load unique prod vars from file
    include_vars:
      file: ~/ansible/env-prod.yml
    when: inventory_hostname == 'prod'

  - name: copy .env dev file with templated vars
    ansible.builtin.template:
      src: ~/ansible/env-dev.j2
      dest: /home/{{ inventory_hostname }}/.env
      owner: '{{ inventory_hostname }}'
      group: '{{ inventory_hostname }}'
      mode: '0600'
    when: inventory_hostname in groups[ 'devs' ]

This works fine but ultimately it is requiring me to create a ton of .yml files when I would rather include some variables in certain steps instead.

Is it possible to load vars for a specific task? I've tried a number of solutions but haven't been able to make it work yet. See below for one method I tried using vars at the end of the task.

  - name: copy .env dev file with templated vars
    ansible.builtin.template:
      src: ~/ansible/env-dev.j2
      dest: /home/{{ inventory_hostname }}/.env
      owner: '{{ inventory_hostname }}'
      group: '{{ inventory_hostname }}'
      mode: '0600'
    when: inventory_hostname in groups[ 'devs' ]
    vars:
       NODE_ENV: development
       PORT: 66

Solution 1:

The key to organize your Ansible code is to rely on group vars.

This feature permits to load variables according to the group a host belong to. You have several ways to do that, one of the clearest way is to use yaml files named with the name of the group in the group_vars folder (plus a all.yaml matching all hosts). Ansible will pick automatically them for you, so you can get rid of your first two include_vars. You can combine them with variables specific to the role and or the playbook. So you end with a set of variables coming from the host (the target) and from the role / playbook (the task to achieve).

To replace the hardcoded src: ~/ansible/env-dev.j2 you could for example define a variable in each group.

---
# dev.yaml
template_name: "env-dev.j2"
---
# prod.yaml
template_name: "env-prod.j2"

And then use it in your playbook / role src: "{{ template_name }}".