> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Magic Variables

> This article explores how magic variables in Ansible simplify accessing variables across hosts and enhance playbook functionality.

In this article, we explore how magic variables in Ansible simplify accessing variables across hosts. Previously, we delved into variable scopes and saw that host variables are defined for each individual host. Now, we will build on that foundation using magic variables.

## Inventory File Example

Consider the following inventory file, where a DNS server is specified for host "web2":

```text theme={null}
/etc/ansible/hosts
web1 ansible_host=172.20.1.100
web2 ansible_host=172.20.1.101 dns_server=10.5.5.4
web3 ansible_host=172.20.1.102
```

When an Ansible playbook starts, it creates separate subprocesses for each host. Before executing tasks on these hosts, Ansible performs variable interpolation by gathering variables from multiple sources and associating them with their respective hosts. As a result, the DNS server IP defined for "web2" is available solely on that host.

> **Tip:**
> If you need to access the DNS server information from another host, magic variables offer a clean solution.

## Using the "hostvars" Magic Variable

The magic variable `hostvars` enables you to retrieve variables set on one host from another host. For example, to retrieve the DNS server defined on "web2", use the following playbook:

```yaml theme={null}
---
- name: Print DNS server IP
  hosts: all
  tasks:
    - debug:
        msg: "{{ hostvars['web2'].dns_server }}"
```

```Ansible theme={null}
PLAY [Check /etc/hosts file] **********************************************************************************

TASK [debug] **************************************************************************************************
ok: [web1] => {
    "dns_server": "10.5.5.4"
}
ok: [web2] => {
    "dns_server": "10.5.5.4"
}
ok: [web3] => {
    "dns_server": "10.5.5.4"
}
```

Because each host is defined with an `ansible_host` parameter, gathering facts permits access to detailed information about other hosts. This includes architecture, devices, mounts, processors, and more. Everything available from a host’s facts can be accessed with `hostvars`. For instance:

```yaml theme={null}
---
- name: Print details from web2
  hosts: all
  tasks:
    - debug:
        msg: "{{ hostvars['web2'].dns_server }}"
    - debug:
        msg: "{{ hostvars['web2'].ansible_host }}"
    - debug:
        msg: "{{ hostvars['web2'].ansible_facts.architecture }}"
    - debug:
        msg: "{{ hostvars['web2'].ansible_facts.devices }}"
    - debug:
        msg: "{{ hostvars['web2'].ansible_facts.mounts }}"
    - debug:
        msg: "{{ hostvars['web2'].ansible_facts.processor }}"
```

Both expression formats yield the same results. You may notice that the official Ansible documentation sometimes presents these expressions with slight variations.

## Exploring Other Magic Variables: "groups" and "group\_names"

Another essential magic variable is `groups`. It returns a list of all hosts within a specified group. In contrast, `group_names` returns all the groups that the current host belongs to.

### Inventory Example with Groups

```Ansible theme={null}
/etc/ansible/hosts
web1 ansible_host=172.20.1.100
web2 ansible_host=172.20.1.101
web3 ansible_host=172.20.1.102

[web_servers]
web1
web2
web3

[americas]
web1
web2

[asia]
web3
```

To retrieve the list of hosts in the "americas" group, you can use:

```yaml theme={null}
- debug:
    msg: "{{ groups['americas'] }}"
```

When running a playbook on host "web1", the `group_names` variable returns the groups that host is a member of (for instance, "web\_servers" and "americas"):

```yaml theme={null}
msg: "{{ group_names }}"
```

## Understanding "inventory\_hostname"

A related magic variable, `inventory_hostname`, returns the hostname as specified in the inventory file rather than its fully qualified domain name (FQDN). For example:

```Ansible theme={null}
/etc/ansible/hosts
web1 ansible_host=172.20.1.100
web2 ansible_host=172.20.1.101
web3 ansible_host=172.20.1.102

[web_servers]
web1
web2
web3

[americas]
web1
web2

[asia]
web3
```

```yaml theme={null}
msg: "{{ inventory_hostname }}"
```

> **Further Reading:**
> For more details on magic variables, consult the official Ansible documentation, especially the sections on variable usage in playbooks.

## Magic Variables in Jinja2 Templates

Magic variables can also be extremely useful in Jinja2 templates. Below are a couple of examples:

```text theme={null}
{{ hostvars['test.example.com']['ansible_facts']['distribution'] }}
```

```jinja2 theme={null}


# Execute tasks that apply to all app servers.


```

## Conclusion

Magic variables in Ansible provide a powerful mechanism to access host-specific variables, aggregated facts, and inventory details across your playbooks. Experimenting with these variables will streamline your workflows and enhance the maintainability of your Ansible configurations.

Happy automating!

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/ansible-advanced-course/module/15e6b588-6cfc-48cd-a773-e365ac3a32ef/lesson/fa524b76-f7e8-46d6-8ae4-a4b02e2e0043" />

  <Card title="Practice Lab" icon="installation" cta="Learn more" href="https://learn.kodekloud.com/user/courses/ansible-advanced-course/module/15e6b588-6cfc-48cd-a773-e365ac3a32ef/lesson/03611566-a4e5-4b29-b26c-b00a7313bcbd" />
</CardGroup>
