Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Synchronize Not Sourcing Multiple Paths #519

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions plugins/action/synchronize.py
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,8 @@ def run(self, tmp=None, task_vars=None):
dest = _tmp_args.get('dest', None)
if src is None or dest is None:
return dict(failed=True, msg="synchronize requires both src and dest parameters are set")
if isinstance(src, str):
src = [src]

# Determine if we need a user@ and a password
user = None
Expand All @@ -357,11 +359,11 @@ def run(self, tmp=None, task_vars=None):
# use the mode to define src and dest's url
if _tmp_args.get('mode', 'push') == 'pull':
# src is a remote path: <user>@<host>, dest is a local path
src = self._process_remote(_tmp_args, src_host, src, user, inv_port in localhost_ports)
src = [self._process_remote(_tmp_args, src_host, e, user, inv_port in localhost_ports) for e in src]
dest = self._process_origin(dest_host, dest, user)
else:
# src is a local path, dest is a remote path: <user>@<host>
src = self._process_origin(src_host, src, user)
src = [self._process_origin(src_host, e, user) for e in src]
dest = self._process_remote(_tmp_args, dest_host, dest, user, inv_port in localhost_ports)

password = dest_host_inventory_vars.get('ansible_ssh_pass', None) or dest_host_inventory_vars.get('ansible_password', None)
Expand All @@ -370,7 +372,7 @@ def run(self, tmp=None, task_vars=None):
else:
# Still need to munge paths (to account for roles) even if we aren't
# copying files between hosts
src = self._get_absolute_path(path=src)
src = [self._get_absolute_path(path=e) for e in src]
dest = self._get_absolute_path(path=dest)

_tmp_args['_local_rsync_password'] = password
Expand Down
22 changes: 16 additions & 6 deletions plugins/modules/synchronize.py
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,17 @@
src: /tmp/localpath/
dest: /tmp/remotepath
rsync_path: /usr/gnu/bin/rsync

# Source files from multiple folders and merge them on the remote
# Files of the same name in /tmp/path_c/ will take precedence over those in /tmp/path_b/, and same for path_b to path_a
- name: Copy files from multiple folders and merge them into dest
ansible.posix.synchronize:
src:
- /tmp/path_a/
- /tmp/path_b/
- /tmp/path_c/
dest: /tmp/dest/
recursive: True
'''


Expand Down Expand Up @@ -395,17 +406,17 @@ def substitute_controller(path):


def is_rsh_needed(source, dest):
if source.startswith('rsync://') or dest.startswith('rsync://'):
if all(e.startswith('rsync://') for e in source) or dest.startswith('rsync://'):
return False
if ':' in source or ':' in dest:
if any(':' in e for e in source) or ':' in dest:
return True
return False


def main():
module = AnsibleModule(
argument_spec=dict(
src=dict(type='path', required=True),
src=dict(type='list', required=True),
dest=dict(type='path', required=True),
dest_port=dict(type='int'),
delete=dict(type='bool', default=False),
Expand Down Expand Up @@ -539,11 +550,10 @@ def main():
if dirs:
cmd.append('--dirs')

if source.startswith('rsync://') and dest.startswith('rsync://'):
if all(e.startswith('rsync://') for e in source) and dest.startswith('rsync://'):
module.fail_json(msg='either src or dest must be a localhost', rc=1)

if is_rsh_needed(source, dest):

# https://github.com/ansible/ansible/issues/15907
has_rsh = False
for rsync_opt in rsync_opts:
Expand Down Expand Up @@ -599,7 +609,7 @@ def main():
changed_marker = '<<CHANGED>>'
cmd.append('--out-format=%s' % shlex_quote(changed_marker + '%i %n%L'))

cmd.append(shlex_quote(source))
[cmd.append(shlex_quote(e)) for e in source]
cmd.append(shlex_quote(dest))
cmdstr = ' '.join(cmd)

Expand Down
Loading