No wizardry wanted to make use of Ansible’s magic variable ‘hostvars’

No Wizardry Needed to Use Ansible's Magic Variable 'hostvars'

No wizardry wanted to make use of Ansible’s magic variable ‘hostvars’

Home » News » No wizardry wanted to make use of Ansible’s magic variable ‘hostvars’
Table of Contents
Image

Image through Pexels from Pixabay

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. ]

author avatar
roosho Senior Engineer (Technical Services)
I am Rakib Raihan RooSho, Jack of all IT Trades. You got it right. Good for nothing. I try a lot of things and fail more than that. That's how I learn. Whenever I succeed, I note that in my cookbook. Eventually, that became my blog. 
share this article.

Enjoying my articles?

Sign up to get new content delivered straight to your inbox.

Please enable JavaScript in your browser to complete this form.
Name