I have a playbook that contains roles for localhost and roles for remote hosts.
In one of the localhost roles I set a fact called git_tag.
I want to use this fact in a template for the remote hosts.
I tried:
- name: Read Version
set_fact:
git_tag: "{{ package_json.stdout | from_json | json_query('version')}}"
delegate_to: "test-server"
But when Ansible reaches the role that reads the template that has {{ git_tag }} it says that git_tag is undefined.
I'm sure I'm doing something wrong. How can I do it?
You should use a hostvars magic variable:
{{ hostvars['localhost']['git_tag'] }}
you can use this
{{ hostvars['test-server']['git_tag'] }}
Related
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 }}
I need to save two 2 IPs to a variable in a vars_file when launching ec2_instances, which are used later during deployment.
This is how I am saving a single server ip:
- name: Save server public IP to vars file
lineinfile: line="server_public_ip{{':'}} {{ item.public_ip }}"
dest="{{ansible_env.HOME}}/dynamic_ips_{{ec2_environment}}"
with_items: server.instances #server is registered in previous task
The output I have in dynamic_ips file is server_public_ip: xxx.xxx.xx.x
Now I have 2 servers launched and registered as servers.
I need to save this as server_public_ips: xxx.xx.x.xx , xxx.x.xx.x
I tried to declare an empty string and append ips to it, something like this, but I am getting errors.
set_fact:
ips: ""
set_fact:
ips: " {{ ips }} + {{ item.public_ip}} "
with_items: servers.instances #servers is registered in previous task
lineinfile: line="server_public_ips{{':'}} {{ ips }}"
dest="{{ansible_env.HOME}}/dynamic_ips_{{ec2_environment}}"
I think it can be done using lineinfile insertafter and regex.
Finally, I need this to do this in a different server,
- name: Restrict access to outside world
command: iptables INPUT {{ item }} ACCEPT
with_items: {{ server_public_ips }}.split(,) #grant access for each ip
command: iptables INPUT DROP
set_fact:
ips: " {{servers.instances | join(',') }} "
should actually work when servers.instances is a list.
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 }}
I have a playbook that spins up a new droplet on DigitalOcean using the core module built into Ansible:
- name: Provision droplet on DigitalOcean
local_action: digital_ocean
state=present
ssh_key_ids=1234
name=mydroplet
client_id=ABC
api_key=ABC
size_id=1
region_id=2
image_id=3
wait_timeout=500
register: my_droplet
- debug: msg="ID is {{ my_droplet.droplet.id }}"
- debug: msg="Your droplet has the IP address of {{ my_droplet.droplet.ip_address }}"
I run this using (note the local argument):
ansible-playbook playbooks/create_droplet.yml -c local -i playbooks/hosts
My hosts file initially looks like this:
[production]
TBA
[localhost]
localhost
When the above playbook finishes I can see the debug information in STDOUT:
ok: [localhost] => {
"msg": "Your droplet has the IP address of 255.255.255.255"
}
Is there any way for this playbook to retain the my_droplet.ip_address variable and save the TBA in the hosts file instead of having to manually copy-pasta it there? I ask because I want to add this provisioning playbook to a ruby script that subsequently bootstraps the VPS with another playbook.
I am doing the same, having written a play that creates servers from a dict (approximately 53 servers at a go, dynamically creating a full test environment). To use a static hosts file, I add the following:
- name: Create in-memory inventory
add_host:
name: "{{ item.value.ServerName }}"
groups: "{{ item.value.RoleTag }},tag_Environment_{{ env_name }}"
when: item.value.template is defined
with_dict: server_details
- name: create file
become: yes
template:
src: ansible-hosts.j2
dest: "{{ wm_inventory_file }}"
The ansible-hosts.j2 template is simply:
{% for item in groups %}
[{{item}}]
{% for entry in groups[item] %}
{{ entry }}
{% endfor %}
{% endfor %}
I'm launching instances with ec2, and I originally wanted to do the same thing. I found some examples of using lineinfile and massaging it to the do the same thing as so:
- name: Launching new instances for {{ application }}
local_action: ec2 group={{ security_group }} instance_type={{ instance_type}} image={{ image }} wait=true region={{ region }} keypair={{ keypair }} vpc_subnet_id={{ subnet }} count={{ instance_count }}
register: ec2
- name: Add instance to local host group
local_action: lineinfile dest=ansible_hosts regexp="{{ item.public_ip }}" insertafter="\[{{ application }}\]" line="{{ item.public_ip }} ansible_ssh_private_key_file=~/ec2-keys/{{ keypair }}.pem" state=present
with_items: ec2.instances
But, I have to agree that it's generally not something you want to do. I found it to be quite a pain. I've since switched to using add_host and life is much better. BTW, application would be the value I used for the group name...
Is there any way for this playbook to retain the my_droplet.ip_address
variable and save the TBA in the hosts file instead of having to
manually copy-pasta it there?
You can retain the ip address of your new host by using the add_host module which allows you to dynamically change the in-memory inventory during an ansible-playbook run. This is useful for when you want to provision a new host and then configure it in a single playbook.
For example
local_action: >
add_host
hostname={{ my_droplet.droplet.id }}
groupname=launched
And then later in your playbook:
- name: Configure instance(s)
hosts: launched
tasks:
...
the second part of your questions:
... and save the TBA in the hosts file instead of having to
manually copy-pasta it there?
There is no built-in ansible way to write additions to the inventory file that is on disk. This is generally not something you want to do. In this case you would need to add it or use a dynamic inventory script to discover the host for future configuration runs.
You should use a dynamic inventory script for this. Using name to distinguish instances, you can subsequently refer to your droplets.
Check https://github.com/ansible/ansible/blob/devel/contrib/inventory/digital_ocean.py for an example script.