Skegg
Skegg

Reputation: 882

Ansible fact setting using set_fact not persisting across runs

I'm trying to understand just how set facts would help me to create "facts" on the fly that I can then use in subsequent runs. To that end I've created this simple YAML to try it out. It isn't behaving the way I thought. Here it is:

- name: record updated mysql root password
  hosts: all
  tasks:
    - name: setting a new fact
      set_fact:
        pwd_updated: True
        cacheable: yes

This runs all fine. However when I try to see if a new fact got added using the setup module, it isn't there

ansible all -m setup -i inventory > ~/ansible_localhost.facts

On running the above command and checking out ansible_localhost.facts I cannot find my new 'fact' viz. pwd_updated. Am I doing something wrong?


UPDATE1

I've followed @VladimirBotka 's advice and now it works just like I wanted.

However I've now enhanced my code (or is it called a script?) such that I now want it to set the fact only if it is not already set. In case it already is, should skip the task and execute the next debug task which should only be executed if the fact is set and not otherwise. Here's the updated code:

- name: record updated mysql root password
  hosts: all
  tasks:
    - name: setting a new fact
      set_fact:
        pwd_updated: True
        cacheable: yes
      when: mysql_root_pwd_updated is undefined
    - debug: 
        var: pwd_updated
      when: mysql_root_pwd_updated is defined

Running for the first time gives:

Using /home/ansible/DevOpsPractice/DevOpsScripts/ansible.cfg as config file

PLAY [record updated mysql root password] **************************************************************************************************************************************************************************************************

TASK [Gathering Facts] *********************************************************************************************************************************************************************************************************************
ok: [localhost]

TASK [setting a new fact] ******************************************************************************************************************************************************************************************************************
ok: [localhost] => {"ansible_facts": {"pwd_updated": true}, "changed": false}

TASK [debug] *******************************************************************************************************************************************************************************************************************************
skipping: [localhost] => {}

PLAY RECAP *********************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0

Running for the second time gives exactly the same:

Using /home/ansible/DevOpsPractice/DevOpsScripts/ansible.cfg as config file

PLAY [record updated mysql root password] **************************************************************************************************************************************************************************************************

TASK [Gathering Facts] *********************************************************************************************************************************************************************************************************************
ok: [localhost]

TASK [setting a new fact] ******************************************************************************************************************************************************************************************************************
ok: [localhost] => {"ansible_facts": {"pwd_updated": true}, "changed": false}

TASK [debug] *******************************************************************************************************************************************************************************************************************************
skipping: [localhost] => {}

PLAY RECAP *********************************************************************************************************************************************************************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0

What am I doing wrong this time?

Upvotes: 1

Views: 5063

Answers (2)

Jack
Jack

Reputation: 6158

To get a "fact" added by the setup module (which is run by gather_facts: yes), add them to the custom facts in /etc/ansible/facts.d/*.fact files.

https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_vars_facts.html#facts-d-or-local-facts

Use the copy module, or template or lineinfile, to create those files. https://medium.com/@jezhalford/ansible-custom-facts-1e1d1bf65db8

Upvotes: 2

Vladimir Botka
Vladimir Botka

Reputation: 67984

You have to configure a cache plugin. See what cache plugins are available

shell> ansible-doc -t cache -l

For example, put the cache into JSON formatted files. See

shell> ansible-doc -t cache jsonfile

and configure the plugin

shell> grep fact_caching ansible.cfg
fact_caching = jsonfile
fact_caching_connection = /tmp/ansible_cache.json
fact_caching_prefix = ansible_facts_
fact_caching_timeout = 86400

Then, given the inventory

shell> cat hosts
host_1
host_2
host_3

the playbook

shell> cat pb.yml 
- hosts: all
  gather_facts: false
  tasks:
    - set_fact:
        pwd_updated: True
        cacheable: yes

gives

shell> ansible-playbook pb.yml

PLAY [all] ***********************************************************************************

TASK [set_fact] ******************************************************************************
ok: [host_1]
ok: [host_2]
ok: [host_3]

PLAY RECAP ***********************************************************************************
host_1: ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
host_2: ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
host_3: ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

and creates the cache at the controller

shell> ls -1 /tmp/ansible_cache.json/ansible_facts_host_*
/tmp/ansible_cache.json/ansible_facts_host_1
/tmp/ansible_cache.json/ansible_facts_host_2
/tmp/ansible_cache.json/ansible_facts_host_3
shell> cat /tmp/ansible_cache.json/ansible_facts_host_*
{
    "pwd_updated": true
}{
    "pwd_updated": true
}{
    "pwd_updated": true
}

The next play will read the cache automatically

shell> cat pb1.yml
- hosts: all
  gather_facts: false
  tasks:
    - debug:
        var: pwd_updated

gives

shell> ansible-playbook pb1.yml 

PLAY [all] ***********************************************************************************

TASK [debug] *********************************************************************************
ok: [host_1] => 
  pwd_updated: true
ok: [host_2] => 
  pwd_updated: true
ok: [host_3] => 
  pwd_updated: true

PLAY RECAP ***********************************************************************************
host_1: ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
host_2: ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
host_3: ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Upvotes: 3

Related Questions