Struggling configuring argument specs for custom module

Hello! I’m developping a custom Ansible module and I’m struggling to set up mu argument specs. I’d like to add some conditionals to it ( like ‘required_one_of’, ‘required_if’ ), but it looks like you’re only able to do it at the top level of the params dict.

Let me explain, here’s my argument specs :

module_args = {
        "config": {
            "elements": "dict",
            "options": {
                "interfaces": {"type": "str", "required": True},
                "vlan": {"type": "str"},
                "pvid": {"type": "str"},
            },
            "type": "list",
        }
    }

What i’d like to do is to make one of the following arguments required : vlan or pvid. I assume to achieve this I should do something like this :

module = AnsibleModule(
        argument_spec = module_args,
        required_one_of = [("config.vlan","config.pvid")],
        supports_check_mode = True
    )

But this doesn’t seem to work, because it looks for config.vlan and config.pvid keys at the top level of the params dict, and it doesn’t go inside of the config dict.

How can I achieve that?

Thanks for your help!

That’s not what the documentation says. If you read through Ansible module architecture — Ansible Community Documentation you’ll see that those appear both in the list of behavioral attributes for arguments and as optional arguments for AnsibleModule().

1 Like

I think there might be a misunderstanding. I understand that options as “required_one_of”, “mutually_exclusive” etc are optional argument for AnsibleModule().

So, for example, with this specific argument_spec dict :

module_args = {
        "config": {
            "elements": "dict",
            "options": {
                "interfaces": {"type": "str", "required": True},
                "vlan": {"type": "str"},
                "pvid": {"type": "str"}
            },
            "type": "list",
            "required": True
        },
        "argument_2": {"type": "str", "required": True},
        "argument_3": {"type": "int", "required": True},
    }

I would add this to my AnsibleModule() argument in order to mutually exclude argument_2 and argument_3

module = AnsibleModule(
  argument_spec,
  mutually_exclusive=[
    ('argument_2', 'argument_3'),
  ]
)

My question is, how can I achieve the same behaviour but with nested elements? For example, if I want to mutually exclude vlan and pvid inside of the config list, what would be the option argument “mutually_exclusive” for AnsibleModule()

Thanks you!

This seems to do what you want, in my limited testing:

module_args = {
        "config": {
            "elements": "dict",
            "options": {
                "interfaces": {"type": "str", "required": True},
                "vlan": {"type": "str"},
                "pvid": {"type": "str"}
            },
            "type": "list",
            "required": True,
            "mutually_exclusive": [["vlan", "pvid"]]
        },
    }

However, based on where you have your “type: list” and the use of the plural “interfaces” for what is a single string, my guess is you still have some issue to work through.

1 Like

Again, that is not correct. They are behavioural attributes for arguments, and also optional arguments for AnsibleModule().

Nothing, because that’s the wrong place to put it. It belongs at the level where those arguments exist, not at the top level.