# Compute variables per host based on group\_vars

**URL:** <https://forum.ansible.com/t/compute-variables-per-host-based-on-group-vars/42596>\
**Category:** Get Help\
**Tags:** variables, python\
**Created:** [May 12, 2025, 9:58am UTC](https://forum.ansible.com/t/compute-variables-per-host-based-on-group-vars/42596 "2025-05-12T09:58:59Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![TheRealBecks](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/therealbecks/32/10020_2.png) [@TheRealBecks](https://forum.ansible.com/u/TheRealBecks)\
**Post date:** [May 12, 2025, 9:58am UTC](https://forum.ansible.com/t/compute-variables-per-host-based-on-group-vars/42596/1 "2025-05-12T09:58:59Z")

</div>

I have some groups defined for each OS under `group_vars`: `debian` and `opensuse` directories. For this example I will only write about `debian`.

I defined this file: `group_vars/all/ansible_groups.yaml`: Abstract groups

In this `debian` directory I defined Debian users and groups:  
`10_groups.yaml`: Abstract groups  
`20_users.yaml`: Abstract users

And then there’s this file:  
`30_users_and_groups.yaml` with that content:

```auto
---
debian_users_and_groups: "{{ debian_users | debian_resolve_users_and_groups(debian_groups, ansible_groups, debian_gids_ids, debian_uids_ids, group_names) }}"

```

As you can see there’s a custom filter with the name `debian_resolve_users_and_groups` that takes the following group vaiables as input:

```auto
debian_users
debian_groups
ansible_groups
debian_gids_ids
debian_uids_ids
group_names

```

So I will get the following variables for each host:

```auto
gids_ids
uids_ids
groups
users
ansible_groups
group_names

```

The filter will compute the `debian_users_and_groups` variable in the `30_users_and_groups.yaml` file. That will be computed per host. The filter is already doing exacly what I want, that’s **already working** ✔

**Next step:**  
I want to get rid of the filter as I think it’s not the best way to handle these variable computations. Instead I thought about using the `VarsModule` class under the `vars_plugins` directory. As I understood that’s the “correct” way to handle variables, did I understood that correctly?

So I created `vars_plugins/debian_users_and_groups.py`. I took the `host_group_vars.py` [file](https://github.com/ansible/ansible/blob/devel/lib/ansible/plugins/vars/host_group_vars.py) as example:

```auto

"""Debian users and groups."""

DOCUMENTATION = """
    name: debian_users_and_groups
    short_description: Generate Debian users and groups per host
    requirements:
        - Enabled in configuration
    description:
        - Loads Debian group data from group_vars/debian/10_groups.yml and user data from group_vars/debian/20_users.yml
    required: True
    vars:
      - debian_users_and_groups
"""

import contextlib
from typing import Any
from ansible.plugins.vars import BaseVarsPlugin
from ansible.utils.vars import combine_vars
from ansible.inventory.host import Host

class VarsModule(BaseVarsPlugin):
    """Generate Debian users and groups per host."""

    REQUIRES_ENABLED = True
    is_stateless = True

    # Functions from the filter will be copied here -->

    def get_vars(self, loader, path, entities, cache=True) -> dict[Any, Any]:
        if not isinstance(entities, list):
            entities = [entities]

        data = {}
        for entity in entities:
            if isinstance(entity, Host):
                #I need to access all hostvars (and the group_vars):
                hostvars = ... # But how?

                # Then I need to get the variables from hostvars or group_vars, don't know:
                gids_ids = hostvars.get("gids_ids", {})
                uids_ids = hostvars.get("uids_ids", {})
                groups = hostvars.get("groups", {})
                users = hostvars.get("users", {})
                ansible_groups = hostvars.get("ansible_groups", {})
                group_names = hostvars.get("group_names", [])

                users_and_groups: dict[Any, Any] = {}

                # Logic from the filter will be copied here -->

                data = combine_vars(data, users_and_groups)

        return data

```

How can I access the already (?) computed `hostvars` (also containing the `group_vars`) for the host?

---

<div class="post-metadata">

**Author:** ![shertel](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/shertel/32/1241_2.png) [@shertel](https://forum.ansible.com/u/shertel)\
**Post date:** [May 12, 2025, 1:36pm UTC](https://forum.ansible.com/t/compute-variables-per-host-based-on-group-vars/42596/2 "2025-05-12T13:36:30Z")

</div>

I think a custom lookup plugin would be a better solution. The [vars](https://github.com/ansible/ansible/blob/devel/lib/ansible/plugins/lookup/vars.py) and [varnames](https://github.com/ansible/ansible/blob/devel/lib/ansible/plugins/lookup/varnames.py) lookups might be able to help, or serve as examples.

```yaml
- name: retrieve variables based on a prefix
  debug:
    msg: "{{ q('vars', *q('varnames', 'debian_.+')) }}"

```

Vars plugins don’t have access to the results of other vars plugins. The Host objects only have access to inventory variables (#3 and #8 in [variable precedence](https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_variables.html#understanding-variable-precedence)):

```python
        data = {}
        for entity in entities:
            if not isinstance(entity, Host):
                continue

            group_vars = {}
            for group in entity.groups:
                group_vars = combine_vars(group_vars, group.get_vars())

            inventory_vars = combine_vars(group_vars, entity.get_vars())

```

---

<div class="post-metadata">

**Author:** ![TheRealBecks](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/therealbecks/32/10020_2.png) [@TheRealBecks](https://forum.ansible.com/u/TheRealBecks)\
**Post date:** [May 12, 2025, 1:50pm UTC](https://forum.ansible.com/t/compute-variables-per-host-based-on-group-vars/42596/3 "2025-05-12T13:50:29Z")

</div>

Thanks @shertel, that already clears up some confusion on my side! If the `vars_plugins` can’t read host and group vars it’s not what I need. Your suggestion of using `vars` or `varnames` is also interesting, bu they ae already working on the task level, but my already in use filter does it job before what I like to preserve. …so… maybe I already found the solution weeks ago by simple using a filter? 😀 At least that filter does its job flawlessly.

---

<div class="post-metadata">

**Author:** ![shertel](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/shertel/32/1241_2.png) [@shertel](https://forum.ansible.com/u/shertel)\
**Post date:** [May 12, 2025, 2:41pm UTC](https://forum.ansible.com/t/compute-variables-per-host-based-on-group-vars/42596/4 "2025-05-12T14:41:27Z")

</div>

If you are looking for an alternative, a custom lookup is a good option, whereas vars plugin is not. I linked to the specific lookup plugins as implementation examples since they’re simple and variable-related, since I don’t know what your filter is doing. You may not be able to easily replace your filter with builtins, but if you can, it could simplify your content.
