# Validating inventory against argument\_specs

**URL:** <https://forum.ansible.com/t/validating-inventory-against-argument-specs/10748>\
**Category:** Get Help\
**Tags:** ansible-lint\
**Created:** [November 7, 2024, 12:29am UTC](https://forum.ansible.com/t/validating-inventory-against-argument-specs/10748 "2024-11-07T00:29:17Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![sourcherry](https://avatars.discourse-cdn.com/v4/letter/s/a3d4f5/32.png) [@sourcherry](https://forum.ansible.com/u/sourcherry)\
**Post date:** [November 7, 2024, 12:29am UTC](https://forum.ansible.com/t/validating-inventory-against-argument-specs/10748/1 "2024-11-07T00:29:17Z")

</div>

Hi, I have been trying to figure out if there’s any way to validate that I have all the necessary variables defined when I include roles from a playbook. If the required arguments for a role are defined in the argument\_specs, then it seems like it should be possible for a tool to check that, given a specific playbook and inventory, all the hosts have the necessary variables defined at the time the role is invoked.

I am aware that ansible-lint is able to check that required arguments to modules are provided, but I’m not able to get similar warnings to ensure arguments are defined when calling a role. I could understand how this might not be easy to do in the general case since one role could include another role, and the variables defined at that point in time could be dynamic in nature (so it may be impossible to know without actually running the whole thing), but for simple single level setups where a playbook includes a role and roles don’t include each other, this could be pretty useful for ensuring that new variables are properly defined on all hosts that need it.

Are there any tools that would help validate this? Or is there some other way to structure my project besides using roles such that I could get this kind of validation? Or maybe if the role validation tasks could be tagged and then I only run that tag with ansible-playbook (to prevent the rest of the role tasks from being run)?

---

<div class="post-metadata">

**Author:** ![jiholland](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/jiholland/32/11273_2.png) [@jiholland](https://forum.ansible.com/u/jiholland)\
**Post date:** [November 7, 2024, 7:15am UTC](https://forum.ansible.com/t/validating-inventory-against-argument-specs/10748/2 "2024-11-07T07:15:48Z")

</div>

Welcome to the forum, @sourcherry

You can test that required arguments in a role [argument\_specs](https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_reuse_roles.html#role-argument-validation) are defined by running the playbook in [check mode](https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_checkmode.html#using-check-mode):

```yaml
$ ansible-playbook playbook.yml --check-mode

```

The playbook will fail when calling the role if you are missing a required argument at the very first task when verifying the arguments, but if it passes `check mode` will not make any changes to your systems.

Calling this example role in a playbook will fail for host2, but not host1:

```yaml
$ cat roles/example/meta/argument_specs.yml
---
argument_specs:  
  main:              
    options:                                                   

      example_required_arg:
        description: "A unique argument that should be defined per host in your inventory."
        type: str
        required: true

      example_default_arg:
        description: "A common argument defined in defaults."
        type: str

$ cat roles/example/defaults/main.yml
---
# example_required_arg: 192.0.2.10
example_default_arg: "Example"

$ cat inventory/host_vars/host1/example.yml
---
example_required_arg: 192.0.2.111

$ cat inventory/host_vars/host2/example.yml
---
example_default_arg: "Test"

```

---

<div class="post-metadata">

**Author:** ![sourcherry](https://avatars.discourse-cdn.com/v4/letter/s/a3d4f5/32.png) [@sourcherry](https://forum.ansible.com/u/sourcherry)\
**Post date:** [November 10, 2024, 1:31am UTC](https://forum.ansible.com/t/validating-inventory-against-argument-specs/10748/3 "2024-11-10T01:31:16Z")

</div>

Thanks for the thoughts. I think check mode is somewhat broken right now (it always fails on certain tasks) and I haven’t bothered to fix it yet but maybe this would be good motivation. This would also require the hosts I’m checking to be online though I think? That wouldn’t be ideal but I might be able to tweak it to still help in some cases.

---

<div class="post-metadata">

**Author:** ![jiholland](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/jiholland/32/11273_2.png) [@jiholland](https://forum.ansible.com/u/jiholland)\
**Post date:** [November 10, 2024, 6:40am UTC](https://forum.ansible.com/t/validating-inventory-against-argument-specs/10748/4 "2024-11-10T06:40:06Z")

</div>

You should strive to make `check mode` and idempotency work for all your tasks.  
Yes, `check mode` requires your hosts to be online.

---

<div class="post-metadata">

**Author:** ![flowerysong](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/flowerysong/32/2305_2.png) [@flowerysong](https://forum.ansible.com/u/flowerysong)\
**Post date:** [November 10, 2024, 4:47pm UTC](https://forum.ansible.com/t/validating-inventory-against-argument-specs/10748/5 "2024-11-10T16:47:39Z")

</div>

> [@jiholland](#):
>
> You should strive to make `check mode` and idempotency work for all your tasks.

I strongly disagree with this. _If you need check mode to work_ it can be reasonable to expend the large amount of effort that requires; if you don’t require it (which many, if not most, people don’t), your time is better spent elsewhere.

---

<div class="post-metadata">

**Author:** ![jiholland](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/jiholland/32/11273_2.png) [@jiholland](https://forum.ansible.com/u/jiholland)\
**Post date:** [November 10, 2024, 7:43pm UTC](https://forum.ansible.com/t/validating-inventory-against-argument-specs/10748/6 "2024-11-10T19:43:08Z")

</div>

Since `check mode` is merely a simulation, I guess it is never required unless you write code to simulate running it. However, since Ansible is often used to describe infrastructure as code, it certainly is nice that most modules support `check mode` so that configuration drift can be discovered before changing it.

---

<div class="post-metadata">

**Author:** ![sourcherry](https://avatars.discourse-cdn.com/v4/letter/s/a3d4f5/32.png) [@sourcherry](https://forum.ansible.com/u/sourcherry)\
**Post date:** [November 11, 2024, 1:44am UTC](https://forum.ansible.com/t/validating-inventory-against-argument-specs/10748/7 "2024-11-11T01:44:27Z")

</div>

Yes idempotency is of very high importance to me, but so far check mode has mostly been a nice to have. It’s definitely nice that ansible has that functionality built in but I’ve been prioritizing other testing mechanisms above check mode up until now. Was just asking about the variable definition checks since that would be one more thing to help catch errors early on along with other tests, ansible lint, etc.

---

<div class="post-metadata">

**Author:** ![jiholland](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/jiholland/32/11273_2.png) [@jiholland](https://forum.ansible.com/u/jiholland)\
**Post date:** [November 11, 2024, 7:34am UTC](https://forum.ansible.com/t/validating-inventory-against-argument-specs/10748/8 "2024-11-11T07:34:16Z")

</div>

I can answer your initial questions straight to the point.

> [@sourcherry](#):
>
> Are there any tools that would help validate this?

`meta/argument_specs.yml` is the only “tool” that will validate the parameters supplied for the role and stop execution if some are missing.

> [@sourcherry](#):
>
> Or is there some other way to structure my project besides using roles such that I could get this kind of validation?

Not to my knowledge.

> [@sourcherry](#):
>
> Or maybe if the role validation tasks could be tagged and then I only run that tag with ansible-playbook (to prevent the rest of the role tasks from being run)?

When an argument specification is defined, a new task is inserted at the beginning of role execution. This task will run regardless of tags, but when you are testing you can add tags to the rest of your tasks and skip those, set the first task in the role to fail, or comment out your tasks.

---

<div class="post-metadata">

**Author:** ![chris](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/chris/32/293_2.png) [@chris](https://forum.ansible.com/u/chris)\
**Post date:** [November 11, 2024, 2:14pm UTC](https://forum.ansible.com/t/validating-inventory-against-argument-specs/10748/9 "2024-11-11T14:14:43Z")

</div>

One thing to note with the argument specification is that it will only validate variables that are defined in it, in other words if the arg spec contains the following:

```yaml
argument_specs:
  main:
    author: Chris Croome
    description: Ansible role for installing and configuring PHP on Debian.
    short_description: The main entry point for the PHP role.
    options:
      php:
        type: bool
        required: true
        description: Run the tasks in this role.

```

And then a `php_foo` variable is used in an inventory this won’t trigger an error, however you can add an additional task to your role that runs in addition to the default arg spec task to catch things like this (see the [example here](https://docs.ansible.com/ansible/latest/playbook_guide/complex_data_manipulation.html#id15) and the [ansible.builtin.validate\_argument\_spec module](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/validate_argument_spec_module.html#examples) which are combined to achieve this [here](https://git.coop/webarch/php/-/blob/05f1e1c52c9b34830c9fd5789479de8f95961408/vars/main.yml#L27) and [here](https://git.coop/webarch/php/-/blob/05f1e1c52c9b34830c9fd5789479de8f95961408/tasks/verify.yml)).

Also you can use `.ansible-lint` to limit the variable names used, for example:

```yaml
var_naming_pattern: "^[php|molecule]_?[a-z0-9_]*$"

```

However the argument spec limits are such that I find I often need to add tasks to check variables, eg:

```yaml
    # https://github.com/composer/composer/issues/12153#issuecomment-2419452358
    - name: Check that the opcache.jit_buffer_size is set to 0 or >= 40961 or >= 1K or >= 1M or >= 1G
      ansible.builtin.assert:
        that:
          - php_conf_opcache_jit_buffer_size is ansible.builtin.regex('^[0-9]{1,20}[G|K|M]?$')
          - >-
            ( php_conf_opcache_jit_buffer_size == "0" ) or
            ( ( php_conf_opcache_jit_buffer_size is ansible.builtin.regex('^[0-9]{1,20}$') ) and
            ( php_conf_opcache_jit_buffer_size | int >= 40961 ) ) or
            ( php_conf_opcache_jit_buffer_size is ansible.builtin.regex('^[1-9][0-9]{0,20}[G|K|M]$') )
        quiet: "{% if ansible_verbosity == 0 %}true{% else %}false{% endif %}"
      loop: "{{ php_conf_opcache_jit_buffer_sizes }}"
      loop_control:
        loop_var: php_conf_opcache_jit_buffer_size
      when: php_conf_opcache_jit_buffer_sizes != []

```

---

<div class="post-metadata">

**Author:** ![kks](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/kks/32/10352_2.png) [@kks](https://forum.ansible.com/u/kks)\
**Post date:** [November 25, 2025, 6:02pm UTC](https://forum.ansible.com/t/validating-inventory-against-argument-specs/10748/10 "2025-11-25T18:02:27Z")

</div>

> [@chris](#):
>
> However the argument spec limits are such that I find I often need to add tasks to check variables, eg:

I do not like to have several places where variables are validated, so I found workaround to use argument spec to validate conditions with any complexity.

Let’s take your example and extend it with additional validation you mentioned.

```yaml
---- argument_specs.yml ----

argument_specs:
  main:
    author: Chris Croome
    description: Ansible role for installing and configuring PHP on Debian.
    short_description: The main entry point for the PHP role.
    options:
      php:
        type: bool
        required: true
        description: Run the tasks in this role.
      validation:
        type: bool
        required: true
        **choices: [true]** # this is bool that can only be true
        description: Validate role options 

---- vars/main.yml ----

# these are role variables

validation_conditions: 
   - "{{ php_conf_opcache_jit_buffer_size is ansible.builtin.regex('^[0-9]{1,20}[G|K|M]?$') }}"
   - "{{ >-
            ( php_conf_opcache_jit_buffer_size == "0" ) or
            ( ( php_conf_opcache_jit_buffer_size is ansible.builtin.regex('^[0-9]{1,20}$') ) and
            ( php_conf_opcache_jit_buffer_size | int >= 40961 ) ) or
            ( php_conf_opcache_jit_buffer_size is ansible.builtin.regex('^[1-9][0-9]{0,20}[G|K|M]$') ) }}"
# pay attention to quotes and curly brackets - they are required, as this is not a condition, but variable value

validation: "{{ validation_conditions is ansible.builtin.all }}"  
# this will be true only if all conditions are true

```

This has drawback that you will not be able to validate conditions for variables that are dynamic (do not passed to the role). For instance you will not be able to validate any conditions that contain ansible\_facts - as facts might not be collected at this point.  
Also you will not be able to add error message for each error (or I could not find a way to do that), There will be only generic error message for argument\_specs failure.

Benefit is that you will be able to set validation to true with ansible external variables - they will overwrite whatever value is calculated in vars/main.yml file.

---

<div class="post-metadata">

**Author:** ![chris](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/chris/32/293_2.png) [@chris](https://forum.ansible.com/u/chris)\
**Post date:** [November 25, 2025, 8:30pm UTC](https://forum.ansible.com/t/validating-inventory-against-argument-specs/10748/11 "2025-11-25T20:30:56Z")

</div>

Wow, thanks, I’ll have a ponder about using this suggestion!
