I know accessing Ansible facts is well documented, but I can't get this code to work.
# site.yml
---
- name: get fact
hosts: webservers
tasks:
- debug: msg="{{ hostvars['web01.example.com']['ansible_all_ipv4_addresses'] }}"
- fail:
When I run it, I get this error:
fatal: [web01.example.com] => One or more undefined variables: 'dict object' has no attribute 'ansible_all_ipv4_addresses'
Yet when I run the command "ansible -i inventory -m setup", I do see the dictionary key:
web01.example.com | success >> {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"<ip_address>"
],
(other objects...)
}
}
This is my inventory file:
# inventory
[webservers]
web01.example.com ansible_host=<ip_address>
I also tried the following hostvars setting but I get the same error:
hostvars['web01.example.com']['ansible_facts']['ansible_all_ipv4_addresses']
What am I doing wrong here? It seems like this should be pretty easy.
It is a little confusing with ansible, but you just use (without ansible_facts in the middle):
hostvars['web01.example.com']['ansible_all_ipv4_addresses']
Or as #oley posted
hostvars[inventory_hostname]['ansible_all_ipv4_addresses']
for the respective host in a task
In documentation you posted it is also always without ansible_facts in the middle, but it is just easy to overlook :)
This should do the trick:
- debug: msg="{{ hostvars[inventory_hostname]['ansible_all_ipv4_addresses'] }}"
Related
I get this error message when running a playbook locally and I cannot figure out why.
fatal: [localhost]: FAILED! =>
msg: |-
The task includes an option with an undefined variable. The error was: /home/{{ new_user }}/.nvs: {{ ansible_user }}: 'ansible_user' is undefined
The error appears to be in '/home/sturm/ansible-dotfiles/playbooks/prephome.yml': line 127, column 7, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
- name: Clone the NVS repo
^ here
Here's the relevant part of the playbook:
# playbooks/prephome.yml
- hosts: all
gather_facts: true
vars_files:
- ../inventories/group_vars/all/vars.yml
tasks:
- name: Clone the NVS repo
ansible.builtin.git:
repo: https://github.com/jasongin/nvs
dest: "{{ nvs_home }}"
version: v1.6.0
And the relevant portion of the variables file:
# inventories/group_vars/all/vars.yml
new_user: "{{ ansible_user }}"
nvs_home: "/home/{{ new_user }}/.nvs"
I thought ansible_user was a built-in variable that always had a value. How can it possibly be 'undefined?'
I've seen other issues talk about how they cannot use ansible_user if their task has become_user in it, but this task clearly does not. So what else could be the problem?
EDIT: I guess I should also note that, when running the playbook, I use the command:
ansible-playbook -K -i "localhost," -c local ./playbooks/prephome.yml
EDIT 2: It might help to see repository from which this problem stems.
TL;DR: I changed the playbook command to:
ansible-playbook -K ./playbooks/prephome.yml
Having a discussion with Jack made me realize that the -i "localhost," -c local portion of the command was not only unnecessary—because I only have a 'localhost' in the inventory—but it was somehow causing the playbook to not see the group_vars files and not set the ansible_user var.
I still don't know the exact reason for it—my money is on the -c local argument. I would certainly be interested as to why removing those arguments from the playbook command suddenly makes the playbook run flawlessly.
This is driving me crazy. My playbook looks as follows:
---
- hosts: all
become_user: root
become_method: sudo
become: yes
vars:
ansible_become_password: "{{ ansible_password }}"
ansible_password is a variable that is supposed to be populated by Ansible Tower / AWX. But I am getting below error message:
fatal: [RHEL8]: FAILED! => {"msg": "The field 'become_pass' has an invalid
value, which includes an undefined variable. The error was: 'ansible_password' is undefined"}
It tells me that ansible_password is undefined. But if I a hardcode the password there and log ansible_password at the end of the playbook execution, i see that ansible_password is well defined. So, it seems like ansible_password is only defined in the scope of tasks.
Anybody has experience with this? What would be the way around this issue?
This error occurs if you don't provide ansible_password variable,
if you run ansible using ansible-playbook command pass ansible_password as argument to your command :
ansible-playbook test.yml -i host.ini -e "ansible_password=YourPassword"
or add it to your host.ini file like:
[all]
0.0.0.0
[all:vars]
ansible_password=YourPassword
or if you use AWX, add this variable to your extra variables:
That should work.
Good luck!
Ansible Version: 2.4.2.0
From here and here, I was able write below playbook
$ cat test.yml
- name: Finding Master VMs
hosts: all-compute-host
remote_user: heat-admin
tasks:
- name: Getting master VM's hostname
shell: hostname
register: hostname_output
- name: Access in different play
hosts: localhost
connection: local
tasks:
- name: Testing vars
debug: var='{{ hostvars[item]['hostname_output']['stdout'] }}'
with_items: groups['all-compute-host']
I don't want use gather_facts: true and access hostname from it. Getting below error when I try to above playbook
-----------OUTPUT REMOVED----------------
TASK [Testing vars] *******************************************************************************************************************
fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: u\"hostvars['groups['all-compute-host']']\" is undefined\n\nThe error appears to have been in '/tmp/test.yml': line 18, column 5, 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: Testing vars\n ^ here\n\nexception type: <class 'ansible.errors.AnsibleUndefinedVariable'>\nexception: u\"hostvars['groups['all-compute-host']']\" is undefined"}
to retry, use: --limit #/tmp/test.retry
-----------OUTPUT REMOVED----------------
I tried below things
debug: var=hostvars[item]['hostname_output']['stdout']
debug: var=hostvars.item.hostname_output.stdout'
I have also tried direct host group instead of iterating item like below
debug: var=hostvars.all-compute-host.hostname_output.stdout'
debug: var=hostvars['all-compute-host']['hostname_output']['stdout']
ok: [localhost] => {
"hostvars['all-compute-host']['hostname_output']['stdout']": "VARIABLE IS NOT DEFINED!"
}
I have also try direct host name.But no use
debug: var='hostvars.compute01.hostname_output.stdout'
The problem is with your debug statement:
tasks:
- name: Testing vars
debug: var='{{ hostvars[item]['hostname_output']['stdout'] }}'
with_items: groups['all-compute-host']
There are two issues:
The value of the var argument to the debug module is evaluated in a Jinja templating context. That means you must not use the {{...}} template markers.
On the hand, the argument to with_items does need the {{...}} markers; without that, you're iterating over a list consisting of a single item, the literal string groups['all-compute-host'].
With both of those problems fixed (and a few minor stylistic changes), you get:
tasks:
- name: Testing vars
debug:
var: hostvars[item].hostname_output.stdout
with_items: "{{ groups['all-compute-host'] }}"
Looking for way to fetch "just" size_available of a particular mount point on remote host from ansible_hosts fact and set that as fact variable in playbook. Can't really figure that out - please share code snippet.
For Ansible 2.8.2 I found that the above solution didn't work and failed with:
templating error while templating string: expected token ',', got 'string'.
The following, however, worked (moving the query text to a variable):
- debug:
msg: "{{ ansible_mounts|json_query(jmesquery) | first }}"
vars:
jmesquery: "[?mount == `/`].size_available"
gives:
"msg": "40047341568"
JSON Query Filter would do the job. For example size_available for mount: /
- debug:
msg: "{{ ansible_mounts|json_query('[?mount == `/`].size_available') }}"
gives:
"msg": [
40047341568
]
I cannot get this seemingly simple example to work in Ansible 1.8.3. The variable interpolation does not kick in the task name. All examples I have seen seem to suggest this should work. Given that the variable is defined in the vars section I expected the task name to print the value of the variable. Why doesn't this work?
Even the example from the Ansible documentation seems to not print the variable value.
---
- hosts: 127.0.0.1
gather_facts: no
vars:
vhost: "foo"
tasks:
- name: create a virtual host file for {{ vhost }}
debug: msg="{{ vhost }}"
This results in the following output:
PLAY [127.0.0.1]
**************************************************************
TASK: [create a virtual host file for {{ vhost }}]
****************************
ok: [127.0.0.1] => {
"msg": "foo"
}
PLAY RECAP
********************************************************************
127.0.0.1 : ok=1 changed=0 unreachable=0 failed=0
Update
This works with 1.7.2 but does not work with 1.8.3. So either this is a bug or a feature.
Variables are not resolved inside the name. Only inside the actual tasks/conditions etc. the placeholders will be resolved. I guess this is by design. Imagine you have a with_items loop and use the {{ item }}in the name. The tasks name will only be printed once, but the {{ item }} would change in every iteration.
I see the examples, even the one in the doc you linked to, use variables in the name. But that doesn't mean the result would be like you expected it. The docs are community managed. It might be someone just put that line there w/o testing it - or maybe it used to work like that in a previous version of Ansible and the docs have not been updated then. (I'm only using Ansible since about one year). But even though it doesn't work like we wish it would, I'm still using variables in my name's, just to indicate that the task is based on dynamic parameters. Might be the examples have been written with the same intention.
An interesting observation I recently made (Ansible 1.9.4) is, default values are written out in the task name.
- name: create a virtual host file for {{ vhost | default("foo") }}
When executed, Ansible would show the task title as:
TASK: [create a virtual host file for foo]
This way you can avoid ugly task names in the output.
Explanation
Whether the variable gets interpolated depends on where it has been declared.
Imagine You have two hosts: A and B.
If variable foo has only per-host values, when Ansible runs the play, it cannot decide which value to use.
On the other hand, if it has a global value (global in a sense of host invariance), there is no confusion which value to use.
Source: https://github.com/ansible/ansible/issues/3103#issuecomment-18835432
Hands on playbook
ansible_user is an inventory variable
greeting is an invariant variable
- name: Test variable substitution in names
hosts: localhost
connection: local
vars:
greeting: Hello
tasks:
- name: Sorry {{ ansible_user }}
debug:
msg: this won't work
- name: You say '{{ greeting }}'
debug:
var: ansible_user
I experienced the same problem today in one of my Ansible roles and I noticed something interesting.
When I use the set_fact module before I use the vars in the task name, they actually get translated to their correct values.
In this example I wanted to set the password for a remote user:
Notice that I use the vars test_user and user_password that I set as facts before.
- name: Prepare to set user password
set_fact:
user_password: "{{ linux_pass }}"
user_salt: "s0m3s4lt"
test_user: "{{ ansible_user }}"
- name: "Changing password for user {{ test_user }} to {{ user_password }}"
user:
name: "{{ ansible_user }}"
password: "{{ user_password | password_hash('sha512', user_salt) }}"
state: present
shell: /bin/bash
update_password: always
This gives me the following output:
TASK [install : Changing password for user linux to LiNuXuSeRPaSs#]
So this solved my problem.
It might be ugly, but you can somewhat workaround with something like this:
- name: create a virtual host file
debug:
msg: "Some command result"
loop: "{{ [ vhost ] }}"
or
- name: create a virtual host file
debug:
msg: "Some command result"
loop_control:
label: "{{ vhost }}"
loop: [1]
I wouldn't do this in general, but it shows how you can use items or label to give information outside of the command result. While it might not
Source: https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html