Search code examples
ansible

Ansible: How to set_fact from Template- / YAML-file?


We typically load a file of YAML code into our playbook using include_vars.

Now there are YAML blocks in the YAML file that we would like to generate using Jinja2.

The YAML file then looks simplified like this:

my_list_from_template:
  {% filter from_yaml %}
  {% for my_os_stage in all_os_stage -%}
  - name: "Template for {{ my_os_stage }}"
  {% endfor %}
  {% endfilter %}

Our playbook looks like this

---
- name: "read tmp/test.yml"
  hosts: localhost
  connection: local
  remote_user: opsadm
  gather_facts: False
  become: yes

  #-----------------------------------------------
  vars:
    all_os_stage:
      - TST
      - DEV
      - INT
      - PRD

  #-----------------------------------------------
  tasks:
    - name: "read tmp/test.yml as template"
      ansible.builtin.set_fact: "{{ lookup('ansible.builtin.template', 'tmp/test.yml') }}"

    - debug:
        msg: "{{ my_list_from_template }}"

However, the debug fails with this error message:

TASK [read tmp/test.yml as template] 
task path: test.yml:19
File lookup using tmp/test.yml as file
ok: [localhost] => {
    "ansible_facts": {
        "_raw_params": "my_list_from_template:\n  [{'name': 'Template for TST'}, {'name': 'Template for DEV'}, {'name': 'Template for INT'}, {'name': 'Template for PRD'}]\n"
    },
    "changed": false
}

TASK [debug]
task path: test.yml:22
fatal: [localhost]: FAILED! => {
    "msg": "The task includes an option with an undefined variable. The error was: 'my_list_from_template' is undefined. 'my_list_from_template' is undefined\n\nThe error appears to be in '/home/oizkrwa/ANS_GIT/LINUX_project_controller_2.4.0/test.yml': line 22, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n    - debug:\n      ^ here\n"
}

How can I solve the problem?


Solution

  • For a Jinja2 Template called templates/my_list.j2 as input and with content of

    my_list_from_template:
      {% for my_os_stage in all_os_stage -%}
      - name: "Template for {{ my_os_stage }}"
      {% endfor %}
    

    processing with a minimal example playbook

    ---
    - hosts: localhost
      become: false
      gather_facts: false
    
      vars:
    
        all_os_stage:
          - TST
          - DEV
          - INT
          - PR
    
      tasks:
    
      - name: "Set from template"
        set_fact:
          my_list: "{{ lookup('ansible.builtin.template', 'templates/my_list.j2') }}"
    
      - debug:
          msg: "{{ my_list | from_yaml }}"
    

    will result into an output of

    TASK [debug] ***************
    ok: [localhost] =>
      msg:
        my_list_from_template:
        - name: Template for TST
        - name: Template for DEV
        - name: Template for INT
        - name: Template for PR