module development and 'with_items'

I’m playing with my module and would like to cram most operations into one transaction under ‘with_items’ according to the docs ‘yum’ and ‘apt’ modules can combine multiple operations generated by ‘with_items’ into one. However I’m a bit puzzled as to what is causing it to behave that way.

http://pastebin.com/hU2csR6b is the code. and here’s the playbook:

  • name: Testing Foo
    foo: name={{ item }} state=present
    with_items:
  • 1
  • 2
  • 3

I expect /tmp/foo to contain 1,2,3 (it seems like that is how yum is receiving it’s list of packages) but I end up with ‘3’ every time (result of file being overwritten 2 times). I’m definitely missing something, but what?

BTW - if there’s a better alternative to ‘with_items’ - I’m all for it, just didn’t see anything close to it

There are some other internals inside of ansible/runner/init.py that do the behind the scenes magic required for the with_items stuff that is done for yum and apt:

https://github.com/ansible/ansible/blob/devel/lib/ansible/runner/init.py#L497

So, in short, it requires modifications to that init.py file to make it work.

thanks for the pointer. Now that makes sense why I couldn’t find anything in the modules themselves.

It also means that unless I hack that file I’m not getting my module to behave similarly.

Is there another way to join operations into a single transaction short of passing their parameters in some comma-separated special-crafted string?

I think I’ve got it:

http://pastebin.com/NCgAhVjF

now works with:

  • name: Testing Foo dicts
    foo:
    name:
    one: 1
    two: 2
    three: 3
    state: present

  • name: Testing Foo lists
    foo:
    name: [ 1, 2, 3]
    state: present

  • name: Testing Foo lists
    foo:
    name:

  • 1

  • 2

  • 3
    state: present

last two result in a simple list iteration, while the first one passes dictionary this should help with my module building… unless somebody is going to point out a better way/inapropriateness of my approach :slight_smile:

"It also means that unless I hack that file I’m not getting my module to behave similarly. "

Basically we’d have to find some way of putting the metadata in the module versus having it in Runner.

This is really a topic for ansible-devel, BTW

should I be filing a github issue or [re]post to ansible-devel then?

i’m always up for revisiting what i did wrong in my ‘wantarray’ patch

I ran into this problem today. I found with_items but with single module call discussed on ansible-devel. I know this thread is old, but has anything changed? I see no discussion of Brian Coca’s wantarray patch on ansible-devel. I see TaskExecutor replaced Runner and that lines 53-55 still refer to a constant when deciding whether to squash loops into a single call.

If this was StackExchange I’d upvote. Instead, I’ll leave this note of endorsement. This example is exactly what I was looking for! It isn’t specific to packaging at all. It’s a general purpose solution to passing arguments into modules. Too bad apt, yum, and pkgng have already been hacked. But let the madness not extend further! Module interfaces shouldn’t rely on with_items. Instead, I’ll be using complex arguments.

this is my idea dump on how to make with_ better/more configurable:

https://github.com/ansible/ansible/issues/12086

it includes a bit more than the 'squash' feature, for now we just
made it configurable so users can enable/disable it by module, going
forward i would like to make it per task as in the example in the
ticket.

FWIW, that code uses type(name) == type(‘’): etc., where isinstance(name,str): (same for list) would be much more Pythonic.