Repository: ansible/ansible

Issue:
Synchronize module fails with multiple items
Synchronize module adds unwanted path fragment to rsync destination when multiple items used (with_items)

Part of task with synchronize action and with_items directive:

``` yaml
- name: 'SOLR | Deploy cores configuration files for instances'
  synchronize: src=projects/{{project_name}}/core-conf/ dest=/opt/solr/home/cores/{{item.name}}/conf/ archive=yes delete=yes rsync_path="sudo rsync"
  register: solrxml
  when: item.solr is defined and item.solr == 'present'
  with_items: instances
  tags:
    - solr
    - solr-conf
    - search
```

Got output:

> TASK: [solr | SOLR | Deploy cores configuration files for instances] *********\* 
> <127.0.0.1> EXEC ['/bin/sh', '-c', 'mkdir -p $HOME/.ansible/tmp/ansible-1383930775.88-164589547782291 && chmod a+rx $HOME/.ansible/tmp/ansible-1383930775.88-164589547782291 && echo $HOME/.ansible/tmp/ansible-1383930775.88-164589547782291']
> <127.0.0.1> PUT /tmp/tmp6nU_52 TO /home/xt/.ansible/tmp/ansible-1383930775.88-164589547782291/synchronize
> <127.0.0.1> EXEC ['/bin/sh', '-c', '/usr/bin/env python /home/xt/.ansible/tmp/ansible-1383930775.88-164589547782291/synchronize; rm -rf /home/xt/.ansible/tmp/ansible-1383930775.88-164589547782291/ >/dev/null 2>&1']
> changed: [10.1.250.10] => (item={'autopull': 'present', 'cron': 'present', 'solr': 'present', 'name': 'dev', 'vhost': 'application', 'domains': 'dev.test.local', 'docroot': u'/var/www/dev', 'db': 'present', 'auth': 'present'}) => {"changed": true, "cmd": "rsync --delay-updates --compress --timeout=10 --delete-after --archive --rsh 'ssh  -o StrictHostKeyChecking=no' --rsync-path 'sudo rsync' --out-format='<<CHANGED>>%i %n%L' projects/test/core-conf/ vagrant@10.1.250.10:/opt/solr/home/cores/dev/conf/", "item": {"auth": "present", "autopull": "present", "cron": "present", "db": "present", "docroot": "/var/www/dev", "domains": "dev.test.local", "name": "dev", "solr": "present", "vhost": "application"}, "msg": ".d....og... ./\n.f....og... admin-extra.html\n.f....og... currency.xml\n.f....og... elevate.xml\n.f....og... mapping-FoldToASCII.txt\n.f....og... mapping-ISOLatin1Accent.txt\n.f....og... protwords.txt\n.f....og... schema.xml\n.f....og... schema_extra_fields.xml\n.f....og... schema_extra_types.xml\n.f....og... scripts.conf\n.f....og... solrconfig.xml\n.f....og... solrconfig_extra.xml\n.f....og... solrcore.properties\n.f....og... spellings.txt\n.f....og... stopwords.txt\n.f....og... synonyms.txt\n.d....og... lang/\n.f....og... lang/contractions_ca.txt\n.f....og... lang/contractions_fr.txt\n.f....og... lang/contractions_ga.txt\n.f....og... lang/contractions_it.txt\n.f....og... lang/hyphenations_ga.txt\n.f....og... lang/stemdict_nl.txt\n.f....og... lang/stoptags_ja.txt\n.f....og... lang/stopwords_ar.txt\n.f....og... lang/stopwords_bg.txt\n.f....og... lang/stopwords_ca.txt\n.f....og... lang/stopwords_cz.txt\n.f....og... lang/stopwords_da.txt\n.f....og... lang/stopwords_de.txt\n.f....og... lang/stopwords_el.txt\n.f....og... lang/stopwords_en.txt\n.f....og... lang/stopwords_es.txt\n.f....og... lang/stopwords_eu.txt\n.f....og... lang/stopwords_fa.txt\n.f....og... lang/stopwords_fi.txt\n.f....og... lang/stopwords_fr.txt\n.f....og... lang/stopwords_ga.txt\n.f....og... lang/stopwords_gl.txt\n.f....og... lang/stopwords_hi.txt\n.f....og... lang/stopwords_hu.txt\n.f....og... lang/stopwords_hy.txt\n.f....og... lang/stopwords_id.txt\n.f....og... lang/stopwords_it.txt\n.f....og... lang/stopwords_ja.txt\n.f....og... lang/stopwords_lv.txt\n.f....og... lang/stopwords_nl.txt\n.f....og... lang/stopwords_no.txt\n.f....og... lang/stopwords_pt.txt\n.f....og... lang/stopwords_ro.txt\n.f....og... lang/stopwords_ru.txt\n.f....og... lang/stopwords_sv.txt\n.f....og... lang/stopwords_th.txt\n.f....og... lang/stopwords_tr.txt\n.f....og... lang/userdict_ja.txt\n.d....og... velocity/\n.f....og... velocity/VM_global_library.vm\n.f....og... velocity/browse.vm\n.f....og... velocity/cluster.vm\n.f....og... velocity/clusterResults.vm\n.f....og... velocity/doc.vm\n.f....og... velocity/facet_fields.vm\n.f....og... velocity/facet_queries.vm\n.f....og... velocity/facet_ranges.vm\n.f....og... velocity/facets.vm\n.f....og... velocity/footer.vm\n.f....og... velocity/head.vm\n.f....og... velocity/header.vm\n.f....og... velocity/hit.vm\n.f....og... velocity/hitGrouped.vm\n.f....og... velocity/jquery.autocomplete.css\n.f....og... velocity/jquery.autocomplete.js\n.f....og... velocity/layout.vm\n.f....og... velocity/main.css\n.f....og... velocity/query.vm\n.f....og... velocity/querySpatial.vm\n.f....og... velocity/suggest.vm\n.f....og... velocity/tabs.vm\n.d....og... xslt/\n.f....og... xslt/example.xsl\n.f....og... xslt/example_atom.xsl\n.f....og... xslt/example_rss.xsl\n.f....og... xslt/luke.xsl\n.f....og... xslt/updateXml.xsl\n", "rc": 0}
> <127.0.0.1> EXEC ['/bin/sh', '-c', 'mkdir -p $HOME/.ansible/tmp/ansible-1383930776.06-136953182056861 && chmod a+rx $HOME/.ansible/tmp/ansible-1383930776.06-136953182056861 && echo $HOME/.ansible/tmp/ansible-1383930776.06-136953182056861']
> <127.0.0.1> PUT /tmp/tmpKJBXPa TO /home/xt/.ansible/tmp/ansible-1383930776.06-136953182056861/synchronize
> <127.0.0.1> EXEC ['/bin/sh', '-c', '/usr/bin/env python /home/xt/.ansible/tmp/ansible-1383930776.06-136953182056861/synchronize; rm -rf /home/xt/.ansible/tmp/ansible-1383930776.06-136953182056861/ >/dev/null 2>&1']
> failed: [10.1.250.10] => (item={'autopull': 'absent', 'cron': 'absent', 'solr': 'present', 'name': 'stage', 'vhost': 'static', 'domains': 'stage.test.local stg.test.local', 'docroot': u'/var/www/stage/current', 'db': 'present', 'auth': 'present'}) => {"cmd": "rsync --delay-updates --compress --timeout=10 --delete-after --archive --rsh 'ssh  -o StrictHostKeyChecking=no' --rsync-path 'sudo rsync' --out-format='<<CHANGED>>%i %n%L' projects/test/core-conf/ vagrant@10.1.250.10:vagrant@10.1.250.10:/opt/solr/home/cores/dev/conf/", "failed": true, "item": {"auth": "present", "autopull": "absent", "cron": "absent", "db": "present", "docroot": "/var/www/stage/current", "domains": "stage.test.local stg.test.local", "name": "stage", "solr": "present", "vhost": "static"}, "rc": 12}
> msg: rsync: mkdir "/home/vagrant/vagrant@10.1.250.10:/opt/solr/home/cores/dev/conf" failed: No such file or directory (2)
> rsync error: error in file IO (code 11) at main.c(605) [Receiver=3.0.9]
> rsync: connection unexpectedly closed (197 bytes received so far) [sender]
> rsync error: error in rsync protocol data stream (code 12) at io.c(226) [sender=3.1.0]

Some of options got duplicated for second item

Ansible: v1.4 (devel)
Python: 2.7

Synchronize module fails with multiple items
Synchronize module adds unwanted path fragment to rsync destination when multiple items used (with_items)

Part of task with synchronize action and with_items directive:

``` yaml
- name: 'SOLR | Deploy cores configuration files for instances'
  synchronize: src=projects/{{project_name}}/core-conf/ dest=/opt/solr/home/cores/{{item.name}}/conf/ archive=yes delete=yes rsync_path="sudo rsync"
  register: solrxml
  when: item.solr is defined and item.solr == 'present'
  with_items: instances
  tags:
    - solr
    - solr-conf
    - search
```

Got output:

> TASK: [solr | SOLR | Deploy cores configuration files for instances] *********\* 
> <127.0.0.1> EXEC ['/bin/sh', '-c', 'mkdir -p $HOME/.ansible/tmp/ansible-1383930775.88-164589547782291 && chmod a+rx $HOME/.ansible/tmp/ansible-1383930775.88-164589547782291 && echo $HOME/.ansible/tmp/ansible-1383930775.88-164589547782291']
> <127.0.0.1> PUT /tmp/tmp6nU_52 TO /home/xt/.ansible/tmp/ansible-1383930775.88-164589547782291/synchronize
> <127.0.0.1> EXEC ['/bin/sh', '-c', '/usr/bin/env python /home/xt/.ansible/tmp/ansible-1383930775.88-164589547782291/synchronize; rm -rf /home/xt/.ansible/tmp/ansible-1383930775.88-164589547782291/ >/dev/null 2>&1']
> changed: [10.1.250.10] => (item={'autopull': 'present', 'cron': 'present', 'solr': 'present', 'name': 'dev', 'vhost': 'application', 'domains': 'dev.test.local', 'docroot': u'/var/www/dev', 'db': 'present', 'auth': 'present'}) => {"changed": true, "cmd": "rsync --delay-updates --compress --timeout=10 --delete-after --archive --rsh 'ssh  -o StrictHostKeyChecking=no' --rsync-path 'sudo rsync' --out-format='<<CHANGED>>%i %n%L' projects/test/core-conf/ vagrant@10.1.250.10:/opt/solr/home/cores/dev/conf/", "item": {"auth": "present", "autopull": "present", "cron": "present", "db": "present", "docroot": "/var/www/dev", "domains": "dev.test.local", "name": "dev", "solr": "present", "vhost": "application"}, "msg": ".d....og... ./\n.f....og... admin-extra.html\n.f....og... currency.xml\n.f....og... elevate.xml\n.f....og... mapping-FoldToASCII.txt\n.f....og... mapping-ISOLatin1Accent.txt\n.f....og... protwords.txt\n.f....og... schema.xml\n.f....og... schema_extra_fields.xml\n.f....og... schema_extra_types.xml\n.f....og... scripts.conf\n.f....og... solrconfig.xml\n.f....og... solrconfig_extra.xml\n.f....og... solrcore.properties\n.f....og... spellings.txt\n.f....og... stopwords.txt\n.f....og... synonyms.txt\n.d....og... lang/\n.f....og... lang/contractions_ca.txt\n.f....og... lang/contractions_fr.txt\n.f....og... lang/contractions_ga.txt\n.f....og... lang/contractions_it.txt\n.f....og... lang/hyphenations_ga.txt\n.f....og... lang/stemdict_nl.txt\n.f....og... lang/stoptags_ja.txt\n.f....og... lang/stopwords_ar.txt\n.f....og... lang/stopwords_bg.txt\n.f....og... lang/stopwords_ca.txt\n.f....og... lang/stopwords_cz.txt\n.f....og... lang/stopwords_da.txt\n.f....og... lang/stopwords_de.txt\n.f....og... lang/stopwords_el.txt\n.f....og... lang/stopwords_en.txt\n.f....og... lang/stopwords_es.txt\n.f....og... lang/stopwords_eu.txt\n.f....og... lang/stopwords_fa.txt\n.f....og... lang/stopwords_fi.txt\n.f....og... lang/stopwords_fr.txt\n.f....og... lang/stopwords_ga.txt\n.f....og... lang/stopwords_gl.txt\n.f....og... lang/stopwords_hi.txt\n.f....og... lang/stopwords_hu.txt\n.f....og... lang/stopwords_hy.txt\n.f....og... lang/stopwords_id.txt\n.f....og... lang/stopwords_it.txt\n.f....og... lang/stopwords_ja.txt\n.f....og... lang/stopwords_lv.txt\n.f....og... lang/stopwords_nl.txt\n.f....og... lang/stopwords_no.txt\n.f....og... lang/stopwords_pt.txt\n.f....og... lang/stopwords_ro.txt\n.f....og... lang/stopwords_ru.txt\n.f....og... lang/stopwords_sv.txt\n.f....og... lang/stopwords_th.txt\n.f....og... lang/stopwords_tr.txt\n.f....og... lang/userdict_ja.txt\n.d....og... velocity/\n.f....og... velocity/VM_global_library.vm\n.f....og... velocity/browse.vm\n.f....og... velocity/cluster.vm\n.f....og... velocity/clusterResults.vm\n.f....og... velocity/doc.vm\n.f....og... velocity/facet_fields.vm\n.f....og... velocity/facet_queries.vm\n.f....og... velocity/facet_ranges.vm\n.f....og... velocity/facets.vm\n.f....og... velocity/footer.vm\n.f....og... velocity/head.vm\n.f....og... velocity/header.vm\n.f....og... velocity/hit.vm\n.f....og... velocity/hitGrouped.vm\n.f....og... velocity/jquery.autocomplete.css\n.f....og... velocity/jquery.autocomplete.js\n.f....og... velocity/layout.vm\n.f....og... velocity/main.css\n.f....og... velocity/query.vm\n.f....og... velocity/querySpatial.vm\n.f....og... velocity/suggest.vm\n.f....og... velocity/tabs.vm\n.d....og... xslt/\n.f....og... xslt/example.xsl\n.f....og... xslt/example_atom.xsl\n.f....og... xslt/example_rss.xsl\n.f....og... xslt/luke.xsl\n.f....og... xslt/updateXml.xsl\n", "rc": 0}
> <127.0.0.1> EXEC ['/bin/sh', '-c', 'mkdir -p $HOME/.ansible/tmp/ansible-1383930776.06-136953182056861 && chmod a+rx $HOME/.ansible/tmp/ansible-1383930776.06-136953182056861 && echo $HOME/.ansible/tmp/ansible-1383930776.06-136953182056861']
> <127.0.0.1> PUT /tmp/tmpKJBXPa TO /home/xt/.ansible/tmp/ansible-1383930776.06-136953182056861/synchronize
> <127.0.0.1> EXEC ['/bin/sh', '-c', '/usr/bin/env python /home/xt/.ansible/tmp/ansible-1383930776.06-136953182056861/synchronize; rm -rf /home/xt/.ansible/tmp/ansible-1383930776.06-136953182056861/ >/dev/null 2>&1']
> failed: [10.1.250.10] => (item={'autopull': 'absent', 'cron': 'absent', 'solr': 'present', 'name': 'stage', 'vhost': 'static', 'domains': 'stage.test.local stg.test.local', 'docroot': u'/var/www/stage/current', 'db': 'present', 'auth': 'present'}) => {"cmd": "rsync --delay-updates --compress --timeout=10 --delete-after --archive --rsh 'ssh  -o StrictHostKeyChecking=no' --rsync-path 'sudo rsync' --out-format='<<CHANGED>>%i %n%L' projects/test/core-conf/ vagrant@10.1.250.10:vagrant@10.1.250.10:/opt/solr/home/cores/dev/conf/", "failed": true, "item": {"auth": "present", "autopull": "absent", "cron": "absent", "db": "present", "docroot": "/var/www/stage/current", "domains": "stage.test.local stg.test.local", "name": "stage", "solr": "present", "vhost": "static"}, "rc": 12}
> msg: rsync: mkdir "/home/vagrant/vagrant@10.1.250.10:/opt/solr/home/cores/dev/conf" failed: No such file or directory (2)
> rsync error: error in file IO (code 11) at main.c(605) [Receiver=3.0.9]
> rsync: connection unexpectedly closed (197 bytes received so far) [sender]
> rsync error: error in rsync protocol data stream (code 12) at io.c(226) [sender=3.1.0]

Some of options got duplicated for second item

Ansible: v1.4 (devel)
Python: 2.7



Discussion:

Resolving patch:
diff --git a/lib/ansible/runner/action_plugins/synchronize.py b/lib/ansible/runner/action_plugins/synchronize.py
--- a/lib/ansible/runner/action_plugins/synchronize.py
+++ b/lib/ansible/runner/action_plugins/synchronize.py
@@ -98,8 +98,8 @@ def run(self, conn, tmp, module_name, module_args,
         if rsync_path:
             options['rsync_path'] = '"' + rsync_path + '"'
 
-        self.runner.module_args = ' '.join(['%s=%s' % (k, v) for (k,
+        module_items = ' '.join(['%s=%s' % (k, v) for (k,
                 v) in options.items()])
         return self.runner._execute_module(conn, tmp, 'synchronize',
-                self.runner.module_args, inject=inject)
+                module_items, inject=inject)
 


Test patch: