I have two servers in my inventory (hosts)
[server] 10.23.12.33 10.23.12.40 and playbook (play.yml)
--- - hosts: all roles: web Inside web role in vars directory i have main.yml
--- file_number : 0 Inside web role in tasks directory i have main.yml
--- - name: Increment variable set_fact: file_number={{ file_number | int + 1 }} - name: create file command: 'touch file{{ file_number }}' Now i expect that in first machine i will have file1 and in second machine i will have file2 but in both machines i have file1
So this variable is local for every machine, how could i make it global for all machines.
My file structure is:
hosts play.yml roles/ web/ tasks/ main.yml vars/ main.yml 33 Answers
Now i expect that in first machine i will have file1 and in second machine i will have file2 but in both machines i have file1
You need to keep in mind that variables in Ansible aren't global. Variables (aka 'facts') are applied uniquely to each host, so file_number for host1 is different than file_number for host2. Here's an example based loosely on what you posted:
roles/test/vars/main.yml:
--- file_number: 0 roles/test/tasks/main.yml:
--- - name: Increment variable set_fact: file_number={{ file_number | int + 1 }} - name: debug debug: msg="file_number is {{ file_number }} on host {{ inventory_hostname }}" Now suppose you have just two hosts defined, and you run this role multiple times in a playbook that looks like this:
--- - hosts: all roles: - { role: test } - hosts: host1 roles: - { role: test } - hosts: all roles: - { role: test } So in the first play the role is applied to both host1 & host2. In the second play it's only run against host1, and in the third play it's again run against both host1 & host2. The output of this playbook is:
PLAY [all] ******************************************************************** TASK: [test | Increment variable] ********************************************* ok: [host1] ok: [host2] TASK: [test | debug] ********************************************************** ok: [host1] => { "msg": "file_number is 1 on host host1" } ok: [host2] => { "msg": "file_number is 1 on host host2" } PLAY [host1] ************************************************** TASK: [test | Increment variable] ********************************************* ok: [host1] TASK: [test | debug] ********************************************************** ok: [host1] => { "msg": "file_number is 2 on host host1" } PLAY [all] ******************************************************************** TASK: [test | Increment variable] ********************************************* ok: [host1] ok: [host2] TASK: [test | debug] ********************************************************** ok: [host1] => { "msg": "file_number is 3 on host host1" } ok: [host2] => { "msg": "file_number is 2 on host host2" } So as you can see, the value of file_number is different for host1 and host2 since the role that increments the value ran against host1 more times than it did host2.
Unfortunately there really isn't a clean way making a variable global within Ansible. The entire nature of Ansible's ability to run tasks in parallel against large numbers of hosts makes something like this very tricky. Unless you're extremely careful with global variables in a parallel environment you can easily trigger a race condition, which will likely result in unpredictable (inconsistent) results.
I haven't found a solution with ansible although i made work around using shell to make global variable for all hosts.
- Create temporary file in /tmp in localhost and place in it the starting count
- Read the file for every host and increment the number inside the file
I created the file and initialized it in the playbook (play.yml)
- name: Manage localhost working area hosts: 127.0.0.1 connection: local tasks: - name: Create localhost tmp file file: path={{ item.path }} state={{ item.state }} with_items: - { path: '/tmp/file_num', state: 'absent' } - { path: '/tmp/file_num', state: 'touch' } - name: Managing tmp files lineinfile: dest=/tmp/file_num line='0' Then in web role in main.tml task i read the file and increment it.
- name: Get file number local_action: shell file=$((`cat /tmp/file_num` + 1)); echo $file | tee /tmp/file_num register: file_num - name: Set file name command: 'touch file{{ file_num.stdout }}' Now i have in first host file1 and in second host file2
0You can use Matt Martz's solution from here.
Basically your task would be like:
- name: Set file name command: 'touch file{{ play_hosts.index(inventory_hostname) }}' And you can remove all that code for maintaining global var and external file.