First, some elementary definitions and laws: In Ansible, there are a collection of reserved variables referred to as magic variables. Because they’re reserved, they can’t be set through customers and, if attempted, Ansible will override them.
This article focuses one magic variable particularly: hostvars
, which will get right of entry to variables outlined for any host in a play at any level in a playbook run.
Most Ansible customers know the stock would possibly comprise further variables which might be assigned to a selected host. Sometimes, those variables related to a number is also wanted through different hosts all over a playbook run. In this text, I’ll make bigger your working out of the usage of hostvars
out of doors of the linear host variable-to-host dating.
[ Compare Ansible vs. Red Hat Ansible Automation Platform ]
Create a easy stock
First, I’ll create a easy ini
kind stock in line with some generic role-playing persona varieties. For simplicity, I can steer clear of the usage of teams
or group_vars
. I’ll additionally steer clear of spinning up any further hosts for this workout through the usage of the loopback for the ansible_host
variable.
stock.ini
servera ansible_host=127.0.0.1 character_type=Bard spell1=Blindness spell2=Confusion
serverb ansible_host=127.0.0.1 character_type=Wizard spell1=Lightning spell2=Fireball
serverc ansible_host=127.0.0.1 character_type=Druid spell1=Poison spell2=Plague
serverd ansible_host=127.0.0.1 character_type=Paladin spell1="Magic Missile" spell2=Fear
Each host is assigned the next variables: ansible_host
, character_type
, spell1
, and spell2
. Each worth, except ansible_host
, is exclusive to the host within the stock.
Display hostvars
I’ll create a playbook to show off the hostvars
to be had to be used. I’ll additionally skip amassing information to streamline the playbook.
example1.yml
---
- identify: Example playbook to show off hostvars
hosts: all
connection: native
gather_facts: false
duties:
- identify: Display the particular hostvars which might be set within the stock for each and every host
ansible.builtin.debug:
var: hostvars[inventory_hostname]|json_query('[character_type,spell1,spell2]')
NOTE: You will have to set up the group.normal assortment to make use of the json_query clear out.
Now, I’ll run the primary playbook:
$ ansible-playbook -i stock.ini example1.yml
example1.yml effects
PLAY [Example playbook to showcase hostvars] ***********************************
TASK [Display all of the hostvars for each host] *******************************
Sunday 09 April 2023 13:09:46 -0400 (0:00:00.018) 0:00:00.018 **********
good enough: [servera] => json_query('[character_type,spell1,spell2]')": [
"Bard",
"Blindness",
"Confusion"
]
good enough: [serverb] => json_query('[character_type,spell1,spell2]')": [
"Wizard",
"Lightning",
"Fireball"
]
good enough: [serverc] => json_query('[character_type,spell1,spell2]')": [
"Druid",
"Poison",
"Plague"
]
good enough: [serverd] =>
"hostvars[inventory_hostname]
PLAY RECAP *********************************************************************
servera : good enough=1 modified=0 unreachable=0 failed=0 skipped=0 rescued=0 disregarded=0
serverb : good enough=1 modified=0 unreachable=0 failed=0 skipped=0 rescued=0 disregarded=0
serverc : good enough=1 modified=0 unreachable=0 failed=0 skipped=0 rescued=0 disregarded=0
serverd : good enough=1 modified=0 unreachable=0 failed=0 skipped=0 rescued=0 disregarded=0
As you’ll be able to see above, the playbook extracted the original hostvars
because it ran in opposition to each and every host. This is a regular use of hostvars
.
[ Write your first Ansible playbook in this hands-on interactive lab. ]
What if I wish to use hostvars from a unique host?
Sometimes, a unmarried host would possibly want a variable from every other host. I’ll take on that during playbook quantity 2.
example2.yml
---
- identify: Example playbook to show off hostvars
hosts: all
gather_facts: false
connection: native
duties:
- identify: Set a reality for servera the usage of serverd host variable
ansible.builtin.set_fact:
opponent: " hostvars['serverd']['character_type'] "
when: inventory_hostname == "servera"
- identify: Print servera hostvars atmosphere derived from a variable from serverd
ansible.builtin.debug:
var: hostvars[inventory_hostname]['opponent']
when:
- opponent is outlined
- identify: Print PvP message
ansible.builtin.debug:
msg:
- "Round1: character_type vs opponent "
when: opponent is outlined
$ ansible-playbook -i stock.ini example2.yml
example2.yml effects
PLAY [Example playbook to showcase hostvars] ***********************************
TASK [Set a fact from serverd to use for servera] ******************************
Sunday 09 April 2023 14:34:19 -0400 (0:00:00.029) 0:00:00.030 **********
skipping: [serverb]
good enough: [servera]
skipping: [serverc]
skipping: [serverd]
TASK [Print servera hostvars setting derived from a variable from serverd] ***************
Sunday 09 April 2023 14:34:20 -0400 (0:00:00.061) 0:00:00.091 **********
skipping: [serverb]
good enough: [servera] =>
"hostvars[inventory_hostname]['opponent']": "Paladin"
skipping: [serverc]
skipping: [serverd]
TASK [Print PvP message] *******************************************************
Sunday 09 April 2023 14:34:20 -0400 (0:00:00.079) 0:00:00.170 **********
good enough: [servera] =>
"msg": [
"Round1: Bard vs Paladin"
]
skipping: [serverb]
skipping: [serverc]
skipping: [serverd]
PLAY RECAP *********************************************************************
servera : good enough=3 modified=0 unreachable=0 failed=0 skipped=0 rescued=0 disregarded=0
serverb : good enough=0 modified=0 unreachable=0 failed=0 skipped=3 rescued=0 disregarded=0
serverc : good enough=0 modified=0 unreachable=0 failed=0 skipped=3 rescued=0 disregarded=0
serverd : good enough=0 modified=0 unreachable=0 failed=0 skipped=3 rescued=0 disregarded=0
Well, that is cool! Using the character_type
variable from serverd
, the playbook may just assign it as a variable for servera
to make use of.
What if I wish to use all explicit hostvars from each and every host on all of the hosts?
Sometimes you wish to have to dynamically get the required host variables from all hosts and use them on all servers. I’ll create playbook 3 to turn this.
example3.yml
---
- identify: Example playbook to show off hostvars
hosts: all
gather_facts: false
connection: native
duties:
- identify: Set a reality referred to as all_character_types
ansible.builtin.set_fact:
all_character_types: "default([]) + [ hostvars[item]['character_type'] ] "
loop: " groups['all'] "
run_once: true
- identify: Print hostvars that displays servera has all character_types
ansible.builtin.debug:
var: all_character_types
when: inventory_hostname == "servera"
- identify: Print hostvars that displays serverb has all character_types
ansible.builtin.debug:
var: all_character_types
when: inventory_hostname == "serverb"
- identify: Print hostvars that displays serverc has all character_types
ansible.builtin.debug:
var: all_character_types
when: inventory_hostname == "serverc"
- identify: Print hostvars that displays serverd has all character_types
ansible.builtin.debug:
var: all_character_types
when: inventory_hostname == "serverd"
Now I’ll run playbook 3:
$ ansible-playbook -i stock.ini example3.yml
example3.yml effects
PLAY [Example playbook to showcase hostvars] ***********************************
TASK [Set a fact called all_character_types] ******************************************
Sunday 09 April 2023 14:59:33 -0400 (0:00:00.030) 0:00:00.030 **********
good enough: [servera] => (merchandise=servera)
good enough: [servera] => (merchandise=serverb)
good enough: [servera] => (merchandise=serverc)
good enough: [servera] => (merchandise=serverd)
TASK [Print hostvars that shows servera has all character_types] *********************
Sunday 09 April 2023 14:59:33 -0400 (0:00:00.080) 0:00:00.111 **********
skipping: [serverb]
good enough: [servera] =>
"all_character_types": [
"Bard",
"Wizard",
"Druid",
"Paladin"
]
skipping: [serverc]
skipping: [serverd]
TASK [Print hostvars that shows serverb has all character_types] *********************
Sunday 09 April 2023 14:59:33 -0400 (0:00:00.056) 0:00:00.167 **********
skipping: [servera]
skipping: [serverc]
good enough: [serverb] =>
"all_character_types": [
"Bard",
"Wizard",
"Druid",
"Paladin"
]
skipping: [serverd]
TASK [Print hostvars that shows serverc has all character_types] *********************
Sunday 09 April 2023 14:59:33 -0400 (0:00:00.054) 0:00:00.221 **********
skipping: [servera]
skipping: [serverb]
good enough: [serverc] =>
"all_character_types": [
"Bard",
"Wizard",
"Druid",
"Paladin"
]
skipping: [serverd]
TASK [Print hostvars that shows serverd has all character_types] *********************
Sunday 09 April 2023 14:59:33 -0400 (0:00:00.053) 0:00:00.275 **********
skipping: [servera]
skipping: [serverb]
skipping: [serverc]
good enough: [serverd] =>
"all_character_types": [
"Bard",
"Wizard",
"Druid",
"Paladin"
]
PLAY RECAP *********************************************************************
servera : good enough=2 modified=0 unreachable=0 failed=0 skipped=3 rescued=0 disregarded=0
serverb : good enough=1 modified=0 unreachable=0 failed=0 skipped=3 rescued=0 disregarded=0
serverc : good enough=1 modified=0 unreachable=0 failed=0 skipped=3 rescued=0 disregarded=0
serverd : good enough=1 modified=0 unreachable=0 failed=0 skipped=3 rescued=0 disregarded=0
In the above output, you’ll be able to see that the playbook units a reality referred to as all_character_types
. You too can see that each and every host now has that reality to be had to it. By making a reality in line with the hostvars
of each and every host, you presently have a listing of all of the character_types
. You can use this reality later.
Spells fight
I’ll create a playbook matching character_types
and a random spell for each and every.
I’ll loop via all the hosts within the stock and leverage the hostvars
of each and every all over the loop. I’ll additionally complement the playbook to make use of the next Jinja filters:
example4.yml
---
- identify: Example playbook to show off hostvars
hosts: all
gather_facts: false
connection: native
duties:
- identify: Select a spell for use in opposition to every other opponent
ansible.builtin.debug:
msg:
- " character_type uses his [spell1,spell2] spell against hostvars[item]['character_type'] "
- " hostvars[item]['character_type'] makes use of hostvars[item][('spell1','spell2') spell against character_type "
loop: "reject('search',inventory_hostname)"
Now I’ll run playbook 4:
$ ansible-playbook -i inventory.ini example4.yml
example4.yml results
PLAY [Example playbook to showcase hostvars] ***********************************
TASK [Select a spell to be used against another opponent] *******************
Sunday 09 April 2023 17:48:38 -0400 (0:00:00.030) 0:00:00.030 **********
good enough: [servera] => (merchandise=serverb) =>
"msg": [
"Bard uses his Blindness spell against Wizard",
"Wizard uses Fireball spell against Bard"
]
good enough: [serverb] => (merchandise=servera) =>
"msg": [
"Wizard uses his Fireball spell against Bard",
"Bard uses Blindness spell against Wizard"
]
good enough: [serverc] => (merchandise=servera) =>
"msg": [
"Druid uses his Plague spell against Bard",
"Bard uses Confusion spell against Druid"
]
good enough: [servera] => (merchandise=serverc) =>
"msg": [
"Bard uses his Confusion spell against Druid",
"Druid uses Poison spell against Bard"
]
good enough: [serverd] => (merchandise=servera) =>
"msg": [
"Paladin uses his Fear spell against Bard",
"Bard uses Confusion spell against Paladin"
]
good enough: [serverb] => (merchandise=serverc) =>
"msg": [
"Wizard uses his Lightning spell against Druid",
"Druid uses Poison spell against Wizard"
]
good enough: [serverc] => (merchandise=serverb) =>
"msg": [
"Druid uses his Poison spell against Wizard",
"Wizard uses Lightning spell against Druid"
]
good enough: [servera] => (merchandise=serverd) =>
"msg": [
"Bard uses his Confusion spell against Paladin",
"Paladin uses Fear spell against Bard"
]
good enough: [serverb] => (merchandise=serverd) =>
"msg": [
"Wizard uses his Fireball spell against Paladin",
"Paladin uses Fear spell against Wizard"
]
good enough: [serverd] => (merchandise=serverb) =>
"msg": [
"Paladin uses his Fear spell against Wizard",
"Wizard uses Lightning spell against Paladin"
]
good enough: [serverc] => (merchandise=serverd) =>
"msg": [
"Druid uses his Poison spell against Paladin",
"Paladin uses Magic Missile spell against Druid"
]
good enough: [serverd] => (merchandise=serverc) =>
"msg": [
"Paladin uses his Magic Missile spell against Druid",
"Druid uses Plague against spell Paladin"
]
PLAY RECAP *********************************************************************
servera : good enough=1 modified=0 unreachable=0 failed=0 skipped=0 rescued=0 disregarded=0
serverb : good enough=1 modified=0 unreachable=0 failed=0 skipped=0 rescued=0 disregarded=0
serverc : good enough=1 modified=0 unreachable=0 failed=0 skipped=0 rescued=0 disregarded=0
serverd : good enough=1 modified=0 unreachable=0 failed=0 skipped=0 rescued=0 disregarded=0
In the general instance, I’ll do a easy extraction of variables from a gaggle the usage of map
and json_query
in opposition to the hostvars
. While that is similar to the primary instance, I’m in truth extracting the hostvars
the usage of the Jinja map clear out. I then go that knowledge to json_query
and seize 2 explicit bits of knowledge
NOTE: The json_query
clear out calls for that you just set up the group.normal
assortment.
example5.yml
---
- identify: Example playbook to show off hostvars
hosts: all
gather_facts: false
connection: native
duties:
- identify: Print explicit hostvars from all teams
ansible.builtin.debug:
var: teams['all'] | map('extract',hostvars)|json_query('[].[character_type,spell2]')
delegate_to: localhost
transform: false
run_once: true
Now I’ll run playbook 5:
$ ansible-playbook -i stock.ini example5.yml
example5.yml effects
PLAY [Example playbook to showcase hostvars] ***********************************
TASK [Print specific hostvars from all groups ] ******************
good enough: [servera -> localhost] => map('extract',hostvars)
PLAY RECAP *********************************************************************
servera : good enough=1 modified=0 unreachable=0 failed=0 skipped=0 rescued=0 disregarded=0
Wrap up
Personally, it took me some time prior to I started the usage of the hostvars
magic variables within the way I’ve proven on this article. However, you would not have to be a magician to make use of hostvars
since the magic is within the examples above. Get previous the semblance of hostvars
being tricky and start the usage of them to your playbooks, duties, and roles. You’ll be amazed at how simple it’s and what sort of your code will strengthen.
[ Need more on Ansible? Take a no-cost technical overview course from Red Hat. Ansible Essentials: Simplicity in Automation Technical Overview. ]
No Comment! Be the first one.