ansibleansible-2.xansible-module

Can I specify that an argument can't be used with a specific choice in Ansible module spec?


I'm looking for a way of specifying that a module argument can't be used if another argument has a certain value. You can specify required_if to require an argument if another argument has a specific value but I need the opposite. Something that's conceptually similar to mutually_exclusive and might be called forbidden_if.

I'm developing a module that creates a login for an SQL server. It can either be a SQL login that's specific to the server or a Windows log in that uses the domain controller. For an SQL login you must specify a password for but you can't for Windows as this is set by the domain controller. Logins have an identifier (SID) that may be specified by the user for SQL logins but can't be for Window.

Although it's a Powershell module for a Windows host I'll use Python examples because that's what the documentation is in.

This is the spec for a module that creates an SQL login

module = AnsibleModule(
    argument_spec=dict(
        username=dict(type='str', required=True),
        password=dict(type='str', no_log=True, required=True),
        sid=dict(type='str', required=False),
    ),
    supports_check_mode=True
)

and one for a Windows login

module = AnsibleModule(
    argument_spec=dict(
        username=dict(type='str', required=True),
    ),
    supports_check_mode=True
)

This is my current attempt at a spec for a combined module

module = AnsibleModule(
    argument_spec=dict(
        username=dict(type='str', required=True),
        password=dict(type='str', no_log=True, required=False),
        sid=dict(type='str', required=False),
        login_type=dict(
            type='str',
            choices=[ 'sql', 'windows' ],
            default='sql',
            required=False
        )
    ),
    required_if=[
        ('login_type', 'sql', ('password')),
    ],
    supports_check_mode=True
)

I was able to make password required for the sql login_type. Since password and sid can't be specified for a windows login so I'd like to prevent them being used if login_type is windows. Is this possible and if so, how do I do it?


Solution

  • I don't see a solution to your problem without coding the test:

    arguments = dict(
        username=dict(type='str', required=True),
        password=dict(type='str', no_log=True, required=False),
        sid=dict(type='str', required=False),
        login_type=dict(
            type='str',
            choices=[ 'sql', 'windows' ],
            default='sql',
            required=False
                )
    )
    module = AnsibleModule(
        argument_spec=arguments,
        required_if=[
            ('login_type', 'sql', ('password',)),
        ],
        supports_check_mode=True
    )
    
    if module.params['login_type'] == 'windows' and (module.params['password'] or module.params['sid']):
        module.fail_json(msg="unable to use 'login_type=windows' with args 'password' or 'sid'")
    

    FYI: I noticed an error in your code, you forgot the , in the test:

    required_if=[
        ('login_type', 'sql', ('password'**,**)),
    ],
    

    Result:

    fatal: [localhost]: FAILED! => {"changed": false, "msg": "unable to use 'login_type=windows' with args 'password' or 'sid'"}