Ansible set_fact across plays

18,251

Solution 1

Facts are host specific. As the documentation about set_fact says, "[v]ariables [set with set_fact] are set on a host-by-host basis".

Instead, I'd try using run_once as defined in Delegation, rolling updates, and local actions, like this:

- hosts: contractsServers
  tasks:
    - name: Determine date
      local_action: shell: date "+%Y_%m_%d" --date="1 days ago"
      register: yesterday
      always_run: True
      changed_when: False
      run_once: True
    - name: Do something else locally
      local_action: ...
      register: some_variable_name
      always_run: True
      changed_when: False
      run_once: True

    - name: Do something remotely using the variables registered above
      ...

Solution 2

You could enable fact-caching. You will need to set up a local redis instance where facts then will be stored.

Share:
18,251

Related videos on Youtube

Mukul Jain
Author by

Mukul Jain

Updated on September 20, 2022

Comments

  • Mukul Jain
    Mukul Jain over 1 year

    I have to run an ansible playbook to execute the following tasks

    1) Calculate date in YYYY_MM_DD format and then use this prefix to download some file from aws to my local machine. The filename is of the following format 2015_06_04_latest_file.csv

    2) I have to then create a folder by the name 2015_06_04 into multiple hosts and upload this file there.

    This is my current playbook -

    ---
    - hosts: 127.0.0.1
      connection: local
      sudo: yes
      gather_facts: no
      tasks:
      - name: calculate date
        shell: date "+%Y_%m_%d" --date="1 days ago"
        register: output
      - name: set date variable
        set_fact: latest_date={{ item }}
        with_items: output.stdout_lines
      - local_action: command mkdir -p /tmp/latest_contracts/{{ latest_date }}
      - local_action: command /root/bin/aws s3 cp s3://primarydatafolder/data/{{ latest_date }}_latest_data.csv  /tmp/latest_contracts/{{ latest_date }}/ creates=/tmp/latest_contracts/{{ latest_date }}/latest_data.csv
        register: result
        ignore_errors: true
      - local_action: command /root/bin/aws s3 cp s3://secondarydatafolder/data/{{ latest_date }}_latest_data.csv  /tmp/latest_contracts/{{ latest_date }}/ creates=/tmp/latest_contracts/{{ latest_date }}/latest_data.csv
        when: result|failed
    # remove the date prefix from the downloaded file
      - local_action: command ./rename_date.sh {{ latest_date }}
        ignore_errors: true 
    - hosts: contractsServers
      sudo: yes
      gather_facts: no
      tasks:
      - name: create directory
        file: path={{item.path}} state=directory mode=0775 owner=root group=root
        with_items:
        - {path: '/var/mukul/contracts/{{ latest_date }}' }
        - {path: '/var/mukul/contracts/dummy' }
      - name: copy dummy contracts
        copy: src=dummy dest=/var/mukul/contracts/
      - name: delete previous symlink
        shell: unlink /var/mukul/contracts/latest
        ignore_errors: true
      - name: upload the newly created latest date folder to the host
        copy: src=/tmp/latest_contracts/{{ latest_date }} dest=/var/mukul/contracts/
      - name: create a symbolic link to the folder on the host and call it latest
        action: file state=link src=/var/mukul/contracts/{{ latest_date }} dest=/var/mukul/contracts/latest
    

    As per ansible's documentation on set_fact variable, this variable latest_date should be available across plays. However, ansible fails with the following message

    failed: [192.168.101.177] => (item={'path': u'/var/mukul/contracts/{# latest_date #}'}) => {"failed": true, "item": {"path": "/var/mukul/contracts/{# latest_date #}"}}
    msg: this module requires key=value arguments (['path=/var/mukul/contracts/{#', 'latest_date', '#}', 'state=directory', 'mode=0775', 'owner=root', 'group=root'])
    

    It looks as if the second playbook is unable to get the value of the latest_date fact. Can you please tell me where i'm making a mistake?

  • Mukul Jain
    Mukul Jain almost 9 years
    Thanks for this. I was looking for ways to do this without fact caching, because to me it seemed a bit too much to do for just maintaining facts across plays.