module development: freestyle parameters

Hi,

I’m trying to extend yum module to allow passing some “extra” options to it that are provided by some of the yum plugins. I would rather avoid enumeration of all possible options (some I don’t even know what they will be!) What is the best way to reflect “freestyle” options like that in module definition:

module = AnsibleModule(
    argument_spec = dict(
        state     = dict(default='present', choices=['present', 'absent']),
        name      = dict(required=True),
        enabled   = dict(required=True, choices=BOOLEANS),
        something = dict(aliases=['whatever'])
        **freestyle = dict()....
    )
)

see that "**freestyle"? Is there a construct I can use to say: if you encounter any unknown arguments - just register them for later analysis? Then in my code I can go through supplied arguments and transform them from "foo=bar" into ['--foo','bar'] parameters I will add to yum_cmd. 

I realize that I can just forgo "magic" AnsibleModule piece and go "manual" but I would rather retain most of yum module as-is since it's a good module and no need to fork it if I don't have to.

I’m thinking it might be better to be more explicit, and have something like:

extra_yum_flags=“–foo asdf --bar xyz”

?

IMO it makes things a bit less consistant (since half of options are passed normally via args and other stuff is “extra_yum_flags” also it makes module bit heavier having to parse getopt args for yum to deconstruct/reconstruct additional params. that is why I was looking for something like my original post. However I got the feeling at the moment it’s a no-go so may have to stick with extra_yum_flags…

Dynamic flag matching would make a typo in another flag very hard to detect

– Michael

Third option, which I've done in a module for my own use: have an
"extra_yum_flags" option which can take a dictionary as an argument:

    - yum:
        state: installed
        name: mypkg
        extra_yum_flags:
          foo: bar
          bam: baz
          red_hat: is an operating system

In my module I also happened to allow the extra argument to be taken as
a string. You'll have to do something like prepending '--' to all the
keys in the dict and replacing '_' with '-' or somesuch, but this is
doable.

For my money, the "extra_yum_flag='--foo bar --bam baz" option seems the
simplest. It's not too much code, however, to notice if the argument is
a dict and deal with it appropriately. In my code, I did:

    def parse_extra_args(args):
        parsed_args = ''

        if isinstance(args, dict):
            for k, v in args.iteritems():
                parsed_args += '--' + k.replace('_', '-') + ' ' + v
        elif isinstance(args, basestring):
            parsed_args = args

        return parsed_args

Also, you shouldn't need to parse the parameters if they're provided in
a string, no? Just pass then straight onto the yum command:

    cmd = yum_basecmd + [extra_yum_args, 'install', pkg]

Or what have you.

This is overkill btw.

Just do type='dict' in the argument_spec, Ansible knows what to do and
will take a dict or key=value strings inside the option.

This is how the ec2 module does instance tags now

-- Michael

Excerpts from Michael DeHaan's message of 2013-12-02 16:15:56 -0500:

This is overkill btw.

Just do type='dict' in the argument_spec, Ansible knows what to do and
will take a dict or key=value strings inside the option.

Right, should have specified: the code I posted is what allows the
string-containing-options or the dict simultaneously. If you want
a dict period, then it is _far_ easier.

thanks guys. I ended up developing specialized module in the end based on yum as repoquery used in yum module has problem with passing params to yum plugins. Well it was worth a try :slight_smile: