Ansible’s strenght is to work with all kinds of devices and services – in one go. To properly call a variable value from one server while working on another host the variable needs to be referenced properly.
One of the major strength about Ansible is the capability to almost seamlessly talk to different hosts, devices and services. That’s agent-less at its best!
However, to do that often variables of one host need to be referenced on another. For the sake of an example, imagine a monitoring server which needs to ssh to the managed nodes. The task is to first collect the public SSH key of the monitoring server and afterwards add it to the managed nodes.
First you need a play to collect the SSH key:
--- - name: fetch ssh key hosts: monitoringserver tasks: - name: fetch ssh key from monitoring server slurp: src: ~/.ssh/id_rsa.pub register: monitoringsshkey
After that, the key needs to be distributed. It makes sense to just add a second play to the same playbook. However, since the ssh key was fetched in the first play, it is not possible to just reference it as {{ monitoringsshkey }}
. That would lead to an error:
fatal: [managednode.qxyz.de]: FAILED! => {"failed": true, "msg": "the field 'args' has an invalid value, which appears to include a variable that is undefined. The error was: 'monitoringsshkey' is undefined\n\nThe error appears to have been in '/home/liquidat/ansible/sshkey.yml': line 19, 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: Distribute SSH to nodes\n ^ here\n"}
Instead, the variable needs to be referenced properly, highlighting the actual host it is coming from:
- name: provide ssh key hosts: managednode.qxyz.de tasks: - name: Distribute SSH to nodes authorized_key: user: liquidat key: "{{ hostvars['monitoringserver']['monitoringsshkey']['content'] | b64decode }}"
The reason for this need is simple: in his example we had only one host targeted in the first play – but it could also easily be five hosts. In that moment, Ansible could not reliably know which variable value to pick if we do not specify the actual host.
Hi!
Great explanation, for me works like a charm, but how about if host monitoringserver is a variable definded in another yml file, for example:
– I have a file called vars.yml with a variable
host_model: someServerHostname
can I use it in that way
key: “{{ hostvars[“{{ host_model }}”][‘monitoringsshkey’][‘content’] | b64decode }}”
Actually is not working for me in that way.
Thanks!
Solution:
key: “{{ hostvars[ host_model][‘monitoringsshkey’][‘content’] | b64decode }}”
😉
Thanks for providing the answer to the question after you figured that out yourself! I really appreciate that 🙂
And yes, there is no need to use curly brackets, you have some outside of the reference already.
awesome, thanks a lot brother….