I'm trying to copy a json file from my localhost to remote hosts, and use the json "version" key value as a parameter in the destination file name.
JSON:
{"name": "test", "version": 3}
YML:
---
- name: Get json file version
hosts: locahost
become: true
tasks:
- name: Register licenses file
command: "cat conf/licenses.json"
register: result
- name: Save the json data
set_fact:
jsondata: "{{ result.stdout | from_json }}"
- name: Save licenses file version
set_fact:
file_version: "{{ jsondata | json_query(jmesquery) }}"
vars:
jmesquery: 'version'
- name: Deploy Licenses File
hosts: hosts
become: true
tasks:
- name: Copy licenses file
copy:
src: "conf/licenses.json"
dest: "/tmp/licenses_{{ file_version }}.json"
When I run the playbook above, the Deploy Licenses File key doesn't find the file_version fact, even though I can see it is successfully saved in the Get json file version key.
Set file_version fact:
ok: [localhost] => {
"ansible_facts": {
"file_version": "1"
},
"changed": false
}
Error:
The task includes an option with an undefined variable. The error was: 'file_version' is undefined
I think the facts are saved on the given host granularity and are not global facts per playbook initiation.
My current workaround is to combine the keys to a single task and then it works correctly, but I prefer to get the version once instead of repeating it for each remote host.
CodePudding user response:
To access facts of another host, you can always use the hostvars
special variable.
So, in your case:
dest: "/tmp/licenses_{{ hostvars.localhost.file_version }}.json"
Now, you actually do not need that level of complication with two plays and could well do:
- name: Deploy Licenses File
hosts: hosts
become: true
tasks:
- name: Copy licenses file
copy:
src: "{{ _licence_file }}"
dest: "/tmp/licenses_{{ file_version }}.json"
vars:
_licence_file: conf/licenses.json
file_version: >-
{{ (lookup('file', _licence_file) | from_json).version }}
CodePudding user response:
The first play runs at localhost only. Therefore the variables declared in the first play are available to localhost only. This is the reason that the variables are not available to host in the second play
The error was: 'file_version' is undefined
Run once the tasks in a block of the first play at all hosts. This way the variables will be available to all hosts in the second play. For example, the simplified playbook below does the job
- hosts: all
tasks:
- block:
- include_vars:
file: licenses.json
name: jsondata
- set_fact:
file_version: "{{ jsondata.version }}"
run_once: true
- hosts: test_11
tasks:
- copy:
src: licenses.json
dest: "/tmp/licenses_{{ file_version }}.json"
Created file at the remote host
shell> ssh admin@test_11 cat /tmp/licenses_3.json
{"name": "test", "version": 3}