Search code examples
ansibleansible-ad-hoc

How to supply both named and free_form arguments to ansible ad-hoc?


I ran across one of Ansible's modules that take free_form arguments along with named arguments - win_command. A specific example is given, where a powershell script is provided on stdin:

- name: Run an executable and send data to the stdin for the executable
  win_command: powershell.exe -
  args:
    stdin: Write-Host test

I want to use this as a one-off task, so I want to use ad-hoc execution in the style of

ansible <host> -m <module> -a <args...>

Unfortunately, I see no info in the documentation on how to deal with a module that requires specifying both free_form and named arguments. Does anyone know?

Putting the named arguments after the free_form argument puts everything in the free_form argument, resulting in powershell complaining about extraneous arguments

... -m win_command -a 'powershell - stdin=C:\some\script.ps1 -arg1 value_1 -arg2 value_2'

PS: I'm aware I could probably stuff both the script path and arguments in the free_form argument, but I am more interested in learning whether this is possible with ad-hoc, as the docs don't say either way.


Solution

  • I can't test the win_command module directly, but with the command module, which is syntactically very similar, you can reproduce this:

    - command: some_command
      args:
        chdir: /tmp
        creates: flagfile
    

    Like this:

    ansible -m command -a 'chdir=/tmp creates=flagfile some_command'
    

    Update

    Upon investigation...the problem you've encountered with stdin isn't a quoting issue; it's that when using the k1=v1 k2=v2 somecommand format of passing parameters to e.g. the command module, Ansible only handles specific keys. In lib/ansible/parsing/splitter.py we see:

    if check_raw and k not in ('creates', 'removes', 'chdir', 'executable', 'warn'):
        raw_params.append(orig_x)
    else:
        options[k.strip()] = unquote(v.strip())
    

    That is, it only recognizes creates, removes, chdir, executable, and warn as module arguments. I would argue that this is a bug in Ansible. Adding support for the stdin argument is trivial, of course:

    if check_raw and k not in ('stdin', 'creates', 'removes', 'chdir', 'executable', 'warn'):
    

    With this change, we can include stdin with spaces as expected:

    $ ansible localhost -m command -a 'chdir=/tmp stdin="Hello world" sed s/Hello/Goodbye/'                                                                    
     [WARNING]: Unable to parse /home/lars/.ansible_hosts as an inventory source
    
     [WARNING]: No inventory was parsed, only implicit localhost is available
    
    localhost | CHANGED | rc=0 >>
    Goodbye world