I'm new to Ansible, I'm trying to use the 'Name' fact that is stored in the hostvars of ansible but, I keep getting variable not set.
I have pumped out all the host vars to confirm it is there, using the following task in my play:
- name: Print all variables for each remote device
debug:
var: hostvars[inventory_hostname]
run_once: true
delegate_to: "{{ groups['dir_tier'] | first }}"
I can see the fact is there, truncated output of hostvars:
{"hostvars[inventory_hostname]":
"{'tld':'{{environment_name}}.{{mgmt_domain}}',
'download_dir':'/tmp',
'archive_file_server':
'{{
file_server
}}',
'transport':
'repositories',
'java_package':
'jdk',
'Name':
'idserver99'
}
Have tried several ways to target the 'Name' but keep coming back to the not defined issue.
hostvars[inventory_hostname][Name]
hostvars[inventory_hostname].[Name]
{{ hostvars[inventory_hostname].[Name] }}
{{ hostvars[inventory_hostname][Name] }}
I dont seem to be able to crack the correct syntax pointer welcome.
Keen to learn.
Related
I'm new to ansible but trying to progress and learn.
I'm running a number of API calls to configure a web proxy tool.
The flow is essentially, make a GET request to see if the object exists, if does not exist, follow up with a POST request to create the object. Pretty standard.
This procedure repeats itself multiple times as the product can have a number of instances of the same type of configuration. So I would like to make the GET/POST routine as generic repeatable as possible, by associating an id.
The playbook is:
set_fact:
'vh_task_id': 01
- name: check virtual host exists
uri:
method: GET
url: "{{ admin_api_url }}/hosts?vHost={{ public_virtual_host|urlencode() }}"
return_content: yes
headers:
X-XSRF-Header: "Access"
user: "{{ admin_user }}"
password: "{{ admin_password }}"
status_code: 200
validate_certs: no
register: response
- name: set fact virtual host task id response '{{ public_virtual_host }}'
set_fact:
'response_{{ vh_task_id }}': "{{ response }}"
This all works fine, up to this point and response_{{ vh_task_id }} correctly contains the response body from the above set_fact, as I can see it, if I output it.
The issue now becomes when I want to query the JSON in response_{{ vh_task_id }} as the variable to query to get the id value.
The set_fact, is setting a literal value ofresponse_01 rather than seeing the concatenation as a registered variable.
Here is an example of how I was trying to do it:
set_fact:
'vh_id': "{{ hostvars[inventory_hostname].response_{{ vh_task_id }} | json_query('json.items[0].id') }}"
Many thanks for any help.
Try this:
set_fact:
'vh_id': "{{ hostvars[inventory_hostname].hostvar | json_query('json.items[0].id') }}"
vars:
hostvar: response_{{ vh_task_id }}
Also you don't need explicit quote ' for plain string as variable name. Like, you can change 'vh_id': to vh_id: if no other reason to keep the name with quotes.
Thanks for your time to come back, I tested this but, in the end, I have since learnt that using the with_items, gives me better results and it more repeatable
I would like to reset a varaible to an empty list on all nodes of my inventory, whether it's already existing or not.
The best I come with is:
- name: clear union_files list
set_fact:
hostvars: "{{ hostvars.item | combine({'union_files': []}) }}"
loop: "{{ groups['all'] }}"
run_once: true
But with this code, I've got this error that I don't understand:
MSG:
|combine expects dictionaries, got Undefined
Why it is saying undefined while I'm setting the dict {'union_files': []}
Have you got any clue? What would by the most ansible way to do so?
There are a couple of things going on with this; first, hostvars.item is not the same as hostvars[item]; the former syntax is designed for a quick-and-dirty way of dereferencing keys in a dict, such as ansible_version.full which is not a variable named full, it's ansible_version["full"]. The latter is looking up a variable key name in the dict
The second thing going on is that you are attempting to assign hostvars as if it were a fact, but it's not a fact, it's a namespace in which facts live. So even if you were to do hostvars: {{ hostvars[item] }} it would create a fact named hostvars in the hostvars namespace
If you just want to clear the union_files fact, then use set_fact as you normally would:
- name: clear union_files list
set_fact:
union_files: []
and, assuming the playbook in which that task lives is hosts: all, then it will cheerfully set, or reset, union_files to [] on every host
Thanks Matthew,
I finally come up with this solution:
- name: clear list
set_fact:
union_files: []
delegate_to: item
loop: "{{ ansible_play_hosts }}"
run_once: true
which do the job.
In Ansible 2.1, I have a role being called by a playbook that needs access to a host file variable. Any thoughts on how to access it?
I am trying to access the ansible_ssh_host in the test1 section of the following inventory host file:
[test1]
test-1 ansible_ssh_host=abc.def.ghi.jkl ansible_ssh_port=1212
[test2]
test2-1 ansible_ssh_host=abc.def.ghi.mno ansible_ssh_port=1212
[test3]
test3-1 ansible_ssh_host=abc.def.ghi.pqr ansible_ssh_port=1212
test3-2 ansible_ssh_host=abc.def.ghi.stu ansible_ssh_port=1212
[all:children]
test1
test2
test3
I have tried accessing the role in the following fashions:
{{ hostvars.ansible_ssh_host }}
and
{{ hostvars.test1.ansible_ssh_host }}
I get this error:
fatal: [localhost]: FAILED! => {"failed": true, "msg": "'ansible.vars.hostvars.HostVars object' has no attribute 'ansible'"}
You are on the right track about hostvars.
This magic variable is used to access information about other hosts.
hostvars is a hash with inventory hostnames as keys.
To access fields of each host, use hostvars['test-1'], hostvars['test2-1'], etc.
ansible_ssh_host is deprecated in favor of ansible_host since 2.0.
So you should first remove "_ssh" from inventory hosts arguments (i.e. to become "ansible_user", "ansible_host", and "ansible_port"), then in your role call it with:
{{ hostvars['your_host_group'].ansible_host }}
[host_group]
host-1 ansible_ssh_host=192.168.0.21 node_name=foo
host-2 ansible_ssh_host=192.168.0.22 node_name=bar
[host_group:vars]
custom_var=asdasdasd
You can access host group vars using:
{{ hostvars['host_group'].custom_var }}
If you need a specific value from specific host, you can use:
{{ hostvars[groups['host_group'][0]].node_name }}
You should be able to use the variable name directly
ansible_ssh_host
Or you can go through hostvars without having to specify the host literally
by using the magic variable inventory_hostname
hostvars[inventory_hostname].ansible_ssh_host
I struggled with this, too. My specific setup is: Your host.ini (with the modern names):
[test3]
test3-1 ansible_host=abc.def.ghi.pqr ansible_port=1212
test3-2 ansible_host=abc.def.ghi.stu ansible_port=1212
plus a play fill_file.yml
---
- remote_user: ec2-user
hosts: test3
tasks:
- name: fill file
template:
src: file.j2
dest: filled_file.txt
plus a template file.j2 , like
{% for host in groups['test3'] %}
{{ hostvars[host].ansible_host }}
{% endfor %}
This worked for me, the result is
abc.def.ghi.pqr
abc.def.ghi.stu
I have to admit it's ansible 2.7, not 2.1. The template is a variation of an example in https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html.
The accepted answer didn't work in my setup. With a template
{{ hostvars['test3'].ansible_host }}
my play fails with "AnsibleUndefinedVariable: \"hostvars['test3']\" is undefined" .
Remark: I tried some variations, but failed, occasionally with "ansible.vars.hostvars.HostVars object has no element "; Some of this might be explained by what they say. in https://github.com/ansible/ansible/issues/13343#issuecomment-160992631
hostvars emulates a dictionary [...]. hostvars is also lazily loaded
I've found also a nice and simple way to address hostsvars right on one of Ansible's Github issues
Looks like you can do this as well:
- debug:
msg: "{{ ansible_ssh_host }}"
Thanks a lot this note was very useful for me!
Was able to send the variable defined under /group_var/vars in the ansible playbook
as indicated below.
tasks:
- name: check service account password expiry
- command:
sh /home/monit/get_ldap_attr.sh {{ item }} {{ LDAP_AUTH_USR }}
In Ansible 2.1, I have a role being called by a playbook that needs access to a host file variable. Any thoughts on how to access it?
I am trying to access the ansible_ssh_host in the test1 section of the following inventory host file:
[test1]
test-1 ansible_ssh_host=abc.def.ghi.jkl ansible_ssh_port=1212
[test2]
test2-1 ansible_ssh_host=abc.def.ghi.mno ansible_ssh_port=1212
[test3]
test3-1 ansible_ssh_host=abc.def.ghi.pqr ansible_ssh_port=1212
test3-2 ansible_ssh_host=abc.def.ghi.stu ansible_ssh_port=1212
[all:children]
test1
test2
test3
I have tried accessing the role in the following fashions:
{{ hostvars.ansible_ssh_host }}
and
{{ hostvars.test1.ansible_ssh_host }}
I get this error:
fatal: [localhost]: FAILED! => {"failed": true, "msg": "'ansible.vars.hostvars.HostVars object' has no attribute 'ansible'"}
You are on the right track about hostvars.
This magic variable is used to access information about other hosts.
hostvars is a hash with inventory hostnames as keys.
To access fields of each host, use hostvars['test-1'], hostvars['test2-1'], etc.
ansible_ssh_host is deprecated in favor of ansible_host since 2.0.
So you should first remove "_ssh" from inventory hosts arguments (i.e. to become "ansible_user", "ansible_host", and "ansible_port"), then in your role call it with:
{{ hostvars['your_host_group'].ansible_host }}
[host_group]
host-1 ansible_ssh_host=192.168.0.21 node_name=foo
host-2 ansible_ssh_host=192.168.0.22 node_name=bar
[host_group:vars]
custom_var=asdasdasd
You can access host group vars using:
{{ hostvars['host_group'].custom_var }}
If you need a specific value from specific host, you can use:
{{ hostvars[groups['host_group'][0]].node_name }}
You should be able to use the variable name directly
ansible_ssh_host
Or you can go through hostvars without having to specify the host literally
by using the magic variable inventory_hostname
hostvars[inventory_hostname].ansible_ssh_host
I struggled with this, too. My specific setup is: Your host.ini (with the modern names):
[test3]
test3-1 ansible_host=abc.def.ghi.pqr ansible_port=1212
test3-2 ansible_host=abc.def.ghi.stu ansible_port=1212
plus a play fill_file.yml
---
- remote_user: ec2-user
hosts: test3
tasks:
- name: fill file
template:
src: file.j2
dest: filled_file.txt
plus a template file.j2 , like
{% for host in groups['test3'] %}
{{ hostvars[host].ansible_host }}
{% endfor %}
This worked for me, the result is
abc.def.ghi.pqr
abc.def.ghi.stu
I have to admit it's ansible 2.7, not 2.1. The template is a variation of an example in https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html.
The accepted answer didn't work in my setup. With a template
{{ hostvars['test3'].ansible_host }}
my play fails with "AnsibleUndefinedVariable: \"hostvars['test3']\" is undefined" .
Remark: I tried some variations, but failed, occasionally with "ansible.vars.hostvars.HostVars object has no element "; Some of this might be explained by what they say. in https://github.com/ansible/ansible/issues/13343#issuecomment-160992631
hostvars emulates a dictionary [...]. hostvars is also lazily loaded
I've found also a nice and simple way to address hostsvars right on one of Ansible's Github issues
Looks like you can do this as well:
- debug:
msg: "{{ ansible_ssh_host }}"
Thanks a lot this note was very useful for me!
Was able to send the variable defined under /group_var/vars in the ansible playbook
as indicated below.
tasks:
- name: check service account password expiry
- command:
sh /home/monit/get_ldap_attr.sh {{ item }} {{ LDAP_AUTH_USR }}
In Ansible 2.1, I have a role being called by a playbook that needs access to a host file variable. Any thoughts on how to access it?
I am trying to access the ansible_ssh_host in the test1 section of the following inventory host file:
[test1]
test-1 ansible_ssh_host=abc.def.ghi.jkl ansible_ssh_port=1212
[test2]
test2-1 ansible_ssh_host=abc.def.ghi.mno ansible_ssh_port=1212
[test3]
test3-1 ansible_ssh_host=abc.def.ghi.pqr ansible_ssh_port=1212
test3-2 ansible_ssh_host=abc.def.ghi.stu ansible_ssh_port=1212
[all:children]
test1
test2
test3
I have tried accessing the role in the following fashions:
{{ hostvars.ansible_ssh_host }}
and
{{ hostvars.test1.ansible_ssh_host }}
I get this error:
fatal: [localhost]: FAILED! => {"failed": true, "msg": "'ansible.vars.hostvars.HostVars object' has no attribute 'ansible'"}
You are on the right track about hostvars.
This magic variable is used to access information about other hosts.
hostvars is a hash with inventory hostnames as keys.
To access fields of each host, use hostvars['test-1'], hostvars['test2-1'], etc.
ansible_ssh_host is deprecated in favor of ansible_host since 2.0.
So you should first remove "_ssh" from inventory hosts arguments (i.e. to become "ansible_user", "ansible_host", and "ansible_port"), then in your role call it with:
{{ hostvars['your_host_group'].ansible_host }}
[host_group]
host-1 ansible_ssh_host=192.168.0.21 node_name=foo
host-2 ansible_ssh_host=192.168.0.22 node_name=bar
[host_group:vars]
custom_var=asdasdasd
You can access host group vars using:
{{ hostvars['host_group'].custom_var }}
If you need a specific value from specific host, you can use:
{{ hostvars[groups['host_group'][0]].node_name }}
You should be able to use the variable name directly
ansible_ssh_host
Or you can go through hostvars without having to specify the host literally
by using the magic variable inventory_hostname
hostvars[inventory_hostname].ansible_ssh_host
I struggled with this, too. My specific setup is: Your host.ini (with the modern names):
[test3]
test3-1 ansible_host=abc.def.ghi.pqr ansible_port=1212
test3-2 ansible_host=abc.def.ghi.stu ansible_port=1212
plus a play fill_file.yml
---
- remote_user: ec2-user
hosts: test3
tasks:
- name: fill file
template:
src: file.j2
dest: filled_file.txt
plus a template file.j2 , like
{% for host in groups['test3'] %}
{{ hostvars[host].ansible_host }}
{% endfor %}
This worked for me, the result is
abc.def.ghi.pqr
abc.def.ghi.stu
I have to admit it's ansible 2.7, not 2.1. The template is a variation of an example in https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html.
The accepted answer didn't work in my setup. With a template
{{ hostvars['test3'].ansible_host }}
my play fails with "AnsibleUndefinedVariable: \"hostvars['test3']\" is undefined" .
Remark: I tried some variations, but failed, occasionally with "ansible.vars.hostvars.HostVars object has no element "; Some of this might be explained by what they say. in https://github.com/ansible/ansible/issues/13343#issuecomment-160992631
hostvars emulates a dictionary [...]. hostvars is also lazily loaded
I've found also a nice and simple way to address hostsvars right on one of Ansible's Github issues
Looks like you can do this as well:
- debug:
msg: "{{ ansible_ssh_host }}"
Thanks a lot this note was very useful for me!
Was able to send the variable defined under /group_var/vars in the ansible playbook
as indicated below.
tasks:
- name: check service account password expiry
- command:
sh /home/monit/get_ldap_attr.sh {{ item }} {{ LDAP_AUTH_USR }}