diff --git a/plugins/action/synchronize.py b/plugins/action/synchronize.py index a171a2b..525a146 100644 --- a/plugins/action/synchronize.py +++ b/plugins/action/synchronize.py @@ -339,6 +339,8 @@ class ActionModule(ActionBase): 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 @@ -365,11 +367,11 @@ class ActionModule(ActionBase): # use the mode to define src and dest's url if _tmp_args.get('mode', 'push') == 'pull': # src is a remote path: @, 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: @ - 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) @@ -378,7 +380,7 @@ class ActionModule(ActionBase): 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 diff --git a/plugins/modules/synchronize.py b/plugins/modules/synchronize.py index d65e08f..93ac512 100644 --- a/plugins/modules/synchronize.py +++ b/plugins/modules/synchronize.py @@ -361,6 +361,17 @@ EXAMPLES = r''' 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 ''' @@ -396,9 +407,9 @@ 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 @@ -406,7 +417,7 @@ def is_rsh_needed(source, dest): 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), @@ -540,11 +551,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: @@ -600,7 +610,7 @@ def main(): changed_marker = '<>' 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)