Search code examples
ansibleansible-facts

Ansible: How to preserve facts across executions?


I am trying to understand how to get facts to be preserved across multiple playbook runs. I have something like this:

- name: Host Check
  block:
  - name: Host Check | Obtain System UUID
    shell:
      cmd: >
        dmidecode --string system-uuid
        | head -c3
    register: uuid

  - name: Host Check | Verify EC2
    set_fact:
      is_ec2: "{{ uuid.stdout == 'ec2' }}"
      cacheable: yes

That chunk of code saves is_ec2 as a fact and is executed by a bigger playbook, let's say setup.yml:

ansible-playbook -i cloud_inventory.ini setup.yml

But then if I wanted to run another playbook, let's say test.yml and tried to access is_ec2 (on the same host), I get the following error:

fatal: [factTest]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'is_ec2' is undefined\n\nThe error appears to be in '/path/to/playbooks/test.yml': line 9, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n  tasks:\n    - name: Print isEC2\n      ^ here\n"}

I am a little confused because while I read this is possible in the docs, I can't get it to work.

This boolean converts the variable into an actual 'fact' which will also be added to the fact cache, if fact caching is enabled. Normally this module creates 'host level variables' and has much higher precedence, this option changes the nature and precedence (by 7 steps) of the variable created. https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable This actually creates 2 copies of the variable, a normal 'set_fact' host variable with high precedence and a lower 'ansible_fact' one that is available for persistance via the facts cache plugin. This creates a possibly confusing interaction with meta: clear_facts as it will remove the 'ansible_fact' but not the host variable.


Solution

  • I was able to solve it!

    While there was nothing wrong with the code above, in order to make it work I needed to enable fact caching and specify the plugin I wanted to use. This can be done in the ansible.cfg file by adding these lines:

    fact_caching = jsonfile
    fact_caching_connection = /path/to/cache/directory/where/a/json/will/be/saved
    

    After that I was able to access those cached facts across executions.

    I was curious to see what the JSON file would look like and it seems like it has the facts that you can gather from the setup module and the cached facts:

    ...
    ...
    
        "ansible_virtualization_tech_host": [],
        "ansible_virtualization_type": "kvm",
        "discovered_interpreter_python": "/usr/bin/python3",
        "gather_subset": [
            "all"
        ],
        "is_ec2": true,
        "module_setup": true
    }