From 32ae6fdd437706cbc54cfdc2f9a60f6276e63181 Mon Sep 17 00:00:00 2001 From: Timothy Appnel Date: Fri, 13 Sep 2013 23:20:00 -0400 Subject: [PATCH 01/10] Return of sychronize module code for take 3 --- .../runner/action_plugins/synchronize.py | 85 ++++++++++ library/files/synchronize | 147 ++++++++++++++++++ 2 files changed, 232 insertions(+) create mode 100644 lib/ansible/runner/action_plugins/synchronize.py create mode 100644 library/files/synchronize diff --git a/lib/ansible/runner/action_plugins/synchronize.py b/lib/ansible/runner/action_plugins/synchronize.py new file mode 100644 index 0000000000..87264475da --- /dev/null +++ b/lib/ansible/runner/action_plugins/synchronize.py @@ -0,0 +1,85 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# (c) 2012-2013, Timothy Appnel +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +import os.path + +from ansible import utils +from ansible.runner.return_data import ReturnData + +class ActionModule(object): + + def __init__(self, runner): + self.runner = runner + + def _process_origin(self, host, path, user): + + if not host in ['127.0.0.1', 'localhost']: + return '%s@%s:%s' % (user, host, path) + else: + return path + + def setup(self, module_name, inject): + ''' Always default to localhost as delegate if None defined ''' + if inject.get('delegate_to') is None: + inject['delegate_to'] = '127.0.0.1' + + def run(self, conn, tmp, module_name, module_args, + inject, complex_args=None, **kwargs): + + ''' generates params and passes them on to the rsync module ''' + + # load up options + + options = {} + if complex_args: + options.update(complex_args) + options.update(utils.parse_kv(module_args)) + + src = options.get('src', None) + dest = options.get('dest', None) + + try: + options['local_rsync_path'] = inject['ansible_rsync_path'] + except KeyError: + pass + + src_host = inject['delegate_to'] + dest_host = inject.get('ansible_ssh_host', inject['inventory_hostname']) + if options.get('mode', 'push') == 'pull': + (dest_host, src_host) = (src_host, dest_host) + if not dest_host is src_host: + user = inject.get('ansible_ssh_user', + self.runner.remote_user) + private_key = inject.get('ansible_ssh_private_key_file', self.runner.private_key_file) + if not private_key is None: + options['private_key'] = private_key + src = self._process_origin(src_host, src, user) + dest = self._process_origin(dest_host, dest, user) + + options['src'] = src + options['dest'] = dest + if 'mode' in options: + del options['mode'] + + # run the synchronize module + + self.runner.module_args = ' '.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) + diff --git a/library/files/synchronize b/library/files/synchronize new file mode 100644 index 0000000000..5e2a038d01 --- /dev/null +++ b/library/files/synchronize @@ -0,0 +1,147 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# (c) 2012-2013, Timothy Appnel +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +import subprocess + +DOCUMENTATION = ''' +--- +module: synchronize +version_added: "1.3" +short_description: Uses rsync to make synchronizing file paths in your playbooks quick and easy. +description: + - This is a wrapper around rsync. Of course you could just use the command action to call rsync yourself, but you also have to add a fair number of boilerplate options and host facts. You still may need to call rsync directly via C(command) or C(shell) depending on your use case. The synchronize action is meant to do common things with C(rsync) easily. It does not provide access to the full power of rsync, but does make most invocations easier to follow. +options: + src: + description: + - Path on the source machine that will be synchronized to the destination; The path can be absolute or relative. + required: true + dest: + description: + - Path on the destination machine that will be synchronized from the source; The path can be absolute or relative. + required: true + mode: + description: + - Specify the direction of the synchroniztion. In push mode the localhost or delgate is the source; In pull mode the remote host in context is the source. + required: false + choices: [ 'push', 'pull' ] + default: 'push' + verbosity: + description: + - An integer controlling the amount of information returned during processing. See the C(-v, --verbose) option of the rsync man page for details. If verbosity is not defined or a value of 0 is assumed, the C(--quiet) option is passed and information is supressed. + required: false + default: 0 + delete: + description: + - Delete files that don't exist (after transfer, not before) in the C(src) path. + choices: [ 'yes', 'no' ] + default: 'no' + required: false + rsync_path: + description: + - Specify the rsync command to run on the remote machine. See C(--rsync-path) on the rsync man page. + required: false +author: Timothy Appnel +''' + +EXAMPLES = ''' +# Synchronization of src on the control machien to dest on the remote hosts +synchronize: src=some/relative/path dest=/some/absolute/path + +# Synchronization of two paths both on the control machine +local_action: synchronize src=some/relative/path dest=/some/absolute/path + +# Synchronization of src on the inventory host to the dest on the localhost in +pull mode +synchronize: mode=pull src=some/relative/path dest=/some/absolute/path + +# Synchronization of src on delegate host to dest on the current inventory host +synchronize: > + src=some/relative/path dest=/some/absolute/path + delegate_to: delegate.host + +# Synchronize and delete files in dest on the remote host that are not found in src of localhost. +synchronize: src=some/relative/path dest=/some/absolute/path delete=yes + +# Synchronize and return verbose information from the rsync transfer. +synchronize: src=some/relative/path dest=/some/absolute/path verbosity=1 + +# Synchronize using an alternate rsync command +synchronize: src=some/relative/path dest=/some/absolute/path rsync_path="sudo rsync" +''' + + +def main(): + module = AnsibleModule( + argument_spec = dict( + src = dict(required=True), + dest = dict(required=True), + verbosity = dict(default=0), + tmp_dir = dict(default=None), + delete = dict(default='no', type='bool'), + private_key = dict(default=None), + rsync_path = dict(default=None), + ), + supports_check_mode = True + ) + + source = module.params['src'] + dest = module.params['dest'] + verbosity = module.params['verbosity'] + delete = module.params['delete'] + private_key = module.params['private_key'] + rsync_path = module.params['rsync_path'] + rsync = module.params.get('local_rsync_path', 'rsync') + temp = os.path.dirname(os.path.realpath(__file__)) + + cmd = '%s --archive --delay-updates --compress' % rsync + if module.check_mode: + cmd = cmd + ' --dry-run' + if verbosity: + cmd = '%s -%s' % (cmd, 'v' * int(verbosity)) + else: + cmd = cmd + ' --quiet' + if temp: + cmd = cmd + ' --temp-dir ' + temp + if delete: + cmd = cmd + ' --delete-after' + if private_key is None: + private_key = '' + else: + private_key = '-i '+ private_key + cmd = cmd + " --rsh '%s %s -o %s'" % ('ssh', private_key, + 'StrictHostKeyChecking=no') # need ssh param + if rsync_path: + cmd = cmd + ' --rsync-path ' + rsync_path + + cmd = ' '.join([cmd, source, dest]) + cmdstr = cmd + cmd = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + (out, err) = cmd.communicate() + if cmd.returncode: + return module.fail_json(msg=err, rc=cmd.returncode, cmd=cmdstr) + else: + return module.exit_json(changed=True, msg=out, + rc=cmd.returncode, cmd=cmdstr, check=module.check_mode) + + +# include magic from lib/ansible/module_common.py +#<> + +main() + From 370784ef611fa2f2fc55d9f59dd1a3916220578f Mon Sep 17 00:00:00 2001 From: Timothy Appnel Date: Thu, 19 Sep 2013 00:07:05 -0400 Subject: [PATCH 02/10] Updated version_added in sychronize module --- library/files/synchronize | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/files/synchronize b/library/files/synchronize index 5e2a038d01..cf4768970b 100644 --- a/library/files/synchronize +++ b/library/files/synchronize @@ -21,7 +21,7 @@ import subprocess DOCUMENTATION = ''' --- module: synchronize -version_added: "1.3" +version_added: "1.4" short_description: Uses rsync to make synchronizing file paths in your playbooks quick and easy. description: - This is a wrapper around rsync. Of course you could just use the command action to call rsync yourself, but you also have to add a fair number of boilerplate options and host facts. You still may need to call rsync directly via C(command) or C(shell) depending on your use case. The synchronize action is meant to do common things with C(rsync) easily. It does not provide access to the full power of rsync, but does make most invocations easier to follow. From 61e726fe82dc184bec0d781463ae7f971f6c364f Mon Sep 17 00:00:00 2001 From: Timothy Appnel Date: Fri, 13 Sep 2013 23:56:25 -0400 Subject: [PATCH 03/10] Fix to local delegate_to override and proper sudo handling from @smoothify --- lib/ansible/runner/action_plugins/synchronize.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/ansible/runner/action_plugins/synchronize.py b/lib/ansible/runner/action_plugins/synchronize.py index 87264475da..fc440dd35f 100644 --- a/lib/ansible/runner/action_plugins/synchronize.py +++ b/lib/ansible/runner/action_plugins/synchronize.py @@ -37,6 +37,11 @@ class ActionModule(object): ''' Always default to localhost as delegate if None defined ''' if inject.get('delegate_to') is None: inject['delegate_to'] = '127.0.0.1' + inject['ansible_connection'] = 'local' + # If sudo is active, disable from the connection set self.sudo to True. + if self.runner.sudo: + self.runner.sudo = False + self.sudo = True def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs): @@ -76,7 +81,13 @@ class ActionModule(object): if 'mode' in options: del options['mode'] - # run the synchronize module + rsync_path = options.get('rsync_path', None) + if not rsync_path and self.sudo: + rsync_path = 'sudo rsync' + + # make sure rsync path is quoted. + if rsync_path: + options['rsync_path'] = '"' + rsync_path + '"' self.runner.module_args = ' '.join(['%s=%s' % (k, v) for (k, v) in options.items()]) From 90867d0d0a6320154cdc977cf35c0bb5609bd6a3 Mon Sep 17 00:00:00 2001 From: Timothy Appnel Date: Sat, 14 Sep 2013 00:01:17 -0400 Subject: [PATCH 04/10] Removed busted tmp_dir option that was a bad idea to begin with. --- library/files/synchronize | 4 ---- 1 file changed, 4 deletions(-) diff --git a/library/files/synchronize b/library/files/synchronize index cf4768970b..1362de5530 100644 --- a/library/files/synchronize +++ b/library/files/synchronize @@ -91,7 +91,6 @@ def main(): src = dict(required=True), dest = dict(required=True), verbosity = dict(default=0), - tmp_dir = dict(default=None), delete = dict(default='no', type='bool'), private_key = dict(default=None), rsync_path = dict(default=None), @@ -106,7 +105,6 @@ def main(): private_key = module.params['private_key'] rsync_path = module.params['rsync_path'] rsync = module.params.get('local_rsync_path', 'rsync') - temp = os.path.dirname(os.path.realpath(__file__)) cmd = '%s --archive --delay-updates --compress' % rsync if module.check_mode: @@ -115,8 +113,6 @@ def main(): cmd = '%s -%s' % (cmd, 'v' * int(verbosity)) else: cmd = cmd + ' --quiet' - if temp: - cmd = cmd + ' --temp-dir ' + temp if delete: cmd = cmd + ' --delete-after' if private_key is None: From d8cd3d603e94c58056dfc392576843beb80de8fd Mon Sep 17 00:00:00 2001 From: Timothy Appnel Date: Sat, 14 Sep 2013 22:34:14 -0400 Subject: [PATCH 05/10] Straightened out the logic for delegate handling in synchronize action module --- lib/ansible/runner/action_plugins/synchronize.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/ansible/runner/action_plugins/synchronize.py b/lib/ansible/runner/action_plugins/synchronize.py index fc440dd35f..9439f4350a 100644 --- a/lib/ansible/runner/action_plugins/synchronize.py +++ b/lib/ansible/runner/action_plugins/synchronize.py @@ -35,13 +35,12 @@ class ActionModule(object): def setup(self, module_name, inject): ''' Always default to localhost as delegate if None defined ''' - if inject.get('delegate_to') is None: + if inject['delegate_to'] is None: inject['delegate_to'] = '127.0.0.1' inject['ansible_connection'] = 'local' # If sudo is active, disable from the connection set self.sudo to True. if self.runner.sudo: self.runner.sudo = False - self.sudo = True def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs): @@ -63,8 +62,14 @@ class ActionModule(object): except KeyError: pass - src_host = inject['delegate_to'] + # from the perspective of the rsync call the delegate is the localhost + src_host = '127.0.0.1' dest_host = inject.get('ansible_ssh_host', inject['inventory_hostname']) + + # edge case: explicit delegate and dest_host are the same + if dest_host == inject['delegate_to']: + dest_host = '127.0.0.1' + if options.get('mode', 'push') == 'pull': (dest_host, src_host) = (src_host, dest_host) if not dest_host is src_host: @@ -82,7 +87,7 @@ class ActionModule(object): del options['mode'] rsync_path = options.get('rsync_path', None) - if not rsync_path and self.sudo: + if not rsync_path and self.runner.sudo: rsync_path = 'sudo rsync' # make sure rsync path is quoted. From 4a30ba3a612d130fb88d455927f7cea54f72a57a Mon Sep 17 00:00:00 2001 From: Timothy Appnel Date: Mon, 16 Sep 2013 00:08:10 -0400 Subject: [PATCH 06/10] Added ingenious change detection trick from @smoothify though at the cost of verbosity controls. (Quiet or verbosity > 1 breaks change detection. Also added better use of module_common methods. --- library/files/synchronize | 33 +++++++++------------------------ 1 file changed, 9 insertions(+), 24 deletions(-) diff --git a/library/files/synchronize b/library/files/synchronize index 1362de5530..7bed56d3c1 100644 --- a/library/files/synchronize +++ b/library/files/synchronize @@ -40,11 +40,6 @@ options: required: false choices: [ 'push', 'pull' ] default: 'push' - verbosity: - description: - - An integer controlling the amount of information returned during processing. See the C(-v, --verbose) option of the rsync man page for details. If verbosity is not defined or a value of 0 is assumed, the C(--quiet) option is passed and information is supressed. - required: false - default: 0 delete: description: - Delete files that don't exist (after transfer, not before) in the C(src) path. @@ -77,9 +72,6 @@ synchronize: > # Synchronize and delete files in dest on the remote host that are not found in src of localhost. synchronize: src=some/relative/path dest=/some/absolute/path delete=yes -# Synchronize and return verbose information from the rsync transfer. -synchronize: src=some/relative/path dest=/some/absolute/path verbosity=1 - # Synchronize using an alternate rsync command synchronize: src=some/relative/path dest=/some/absolute/path rsync_path="sudo rsync" ''' @@ -90,7 +82,6 @@ def main(): argument_spec = dict( src = dict(required=True), dest = dict(required=True), - verbosity = dict(default=0), delete = dict(default='no', type='bool'), private_key = dict(default=None), rsync_path = dict(default=None), @@ -100,7 +91,6 @@ def main(): source = module.params['src'] dest = module.params['dest'] - verbosity = module.params['verbosity'] delete = module.params['delete'] private_key = module.params['private_key'] rsync_path = module.params['rsync_path'] @@ -109,10 +99,6 @@ def main(): cmd = '%s --archive --delay-updates --compress' % rsync if module.check_mode: cmd = cmd + ' --dry-run' - if verbosity: - cmd = '%s -%s' % (cmd, 'v' * int(verbosity)) - else: - cmd = cmd + ' --quiet' if delete: cmd = cmd + ' --delete-after' if private_key is None: @@ -122,19 +108,18 @@ def main(): cmd = cmd + " --rsh '%s %s -o %s'" % ('ssh', private_key, 'StrictHostKeyChecking=no') # need ssh param if rsync_path: - cmd = cmd + ' --rsync-path ' + rsync_path - + cmd = cmd + " --rsync-path '%s'" %(rsync_path) + changed_marker = '<>' + cmd = cmd + " --out-format='" + changed_marker + "%i %n%L'" cmd = ' '.join([cmd, source, dest]) cmdstr = cmd - cmd = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - (out, err) = cmd.communicate() - if cmd.returncode: - return module.fail_json(msg=err, rc=cmd.returncode, cmd=cmdstr) + (rc, out, err) = module.run_command(cmd) + if rc: + return module.fail_json(msg=err, rc=rc, cmd=cmdstr) else: - return module.exit_json(changed=True, msg=out, - rc=cmd.returncode, cmd=cmdstr, check=module.check_mode) - + changed = changed_marker in out + return module.exit_json(changed=changed, msg=out.replace(changed_marker,''), + rc=rc, cmd=cmdstr) # include magic from lib/ansible/module_common.py #<> From c1bec5fa074d13464392c37bf4e4452263b134e0 Mon Sep 17 00:00:00 2001 From: Timothy Appnel Date: Wed, 18 Sep 2013 21:17:50 -0400 Subject: [PATCH 07/10] Added archive options to sychronize module as suggested by @smoothify but with a different default scheme to keep param definitions to a minimum. --- library/files/synchronize | 48 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/library/files/synchronize b/library/files/synchronize index 7bed56d3c1..988a4a97d6 100644 --- a/library/files/synchronize +++ b/library/files/synchronize @@ -85,6 +85,14 @@ def main(): delete = dict(default='no', type='bool'), private_key = dict(default=None), rsync_path = dict(default=None), + archive = dict(default='yes', type='bool'), + dirs = dict(type='bool'), + recursive = dict(type='bool'), + links = dict(type='bool'), + perms = dict(type='bool'), + times = dict(type='bool'), + owner = dict(type='bool'), + group = dict(type='bool'), ), supports_check_mode = True ) @@ -95,12 +103,50 @@ def main(): private_key = module.params['private_key'] rsync_path = module.params['rsync_path'] rsync = module.params.get('local_rsync_path', 'rsync') + archive = module.params['archive'] + dirs = module.params['dirs'] + # the default of these params depends on the value of archive + recursive = module.params['recursive'] + links = module.params['links'] + perms = module.params['perms'] + times = module.params['times'] + owner = module.params['owner'] + group = module.params['group'] - cmd = '%s --archive --delay-updates --compress' % rsync + cmd = '%s --delay-updates --compress' % rsync if module.check_mode: cmd = cmd + ' --dry-run' if delete: cmd = cmd + ' --delete-after' + if archive: + cmd = cmd + ' --archive' + if recursive is False: + cmd = cmd + ' --no-recursive' + if links is False: + cmd = cmd + ' --no-links' + if perms is False: + cmd = cmd + ' --no-perms' + if times is False: + cmd = cmd + ' --no-times' + if owner is False: + cmd = cmd + ' --no-owner' + if group is False: + cmd = cmd + ' --no-group' + else: + if recursive is True: + cmd = cmd + ' --recursive' + if links is True: + cmd = cmd + ' --links' + if perms is True: + cmd = cmd + ' --perms' + if times is True: + cmd = cmd + ' --times' + if owner is True: + cmd = cmd + ' --owner' + if group is True: + cmd = cmd + ' --group' + if dirs: + cmd = cmd + ' --dirs' if private_key is None: private_key = '' else: From c2e412981243defae4540d800f3e3384676cd543 Mon Sep 17 00:00:00 2001 From: Timothy Appnel Date: Thu, 19 Sep 2013 02:25:33 -0400 Subject: [PATCH 08/10] Modified changed marker in sychronize module --- library/files/synchronize | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/files/synchronize b/library/files/synchronize index 988a4a97d6..201dd524cc 100644 --- a/library/files/synchronize +++ b/library/files/synchronize @@ -155,7 +155,7 @@ def main(): 'StrictHostKeyChecking=no') # need ssh param if rsync_path: cmd = cmd + " --rsync-path '%s'" %(rsync_path) - changed_marker = '<>' + changed_marker = '<>' cmd = cmd + " --out-format='" + changed_marker + "%i %n%L'" cmd = ' '.join([cmd, source, dest]) cmdstr = cmd From 99f616ecff93191ceaf2f8998b40ea910f332e5b Mon Sep 17 00:00:00 2001 From: Timothy Appnel Date: Thu, 19 Sep 2013 03:09:17 -0400 Subject: [PATCH 09/10] Added docs for archive options in sychronize module. Added missing default value for dirs option. --- library/files/synchronize | 61 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/library/files/synchronize b/library/files/synchronize index 201dd524cc..73daf5962b 100644 --- a/library/files/synchronize +++ b/library/files/synchronize @@ -40,12 +40,60 @@ options: required: false choices: [ 'push', 'pull' ] default: 'push' + archive: + description: + - Mirrors the rsync archive flag, enables recursive, links, perms, times, owner, group flags and -D. + choices: [ 'yes', 'no' ] + default: 'yes' + required: false delete: description: - Delete files that don't exist (after transfer, not before) in the C(src) path. choices: [ 'yes', 'no' ] default: 'no' required: false + dirs: + description: + - Transfer directories without recursing + choices: [ 'yes', 'no' ] + default: 'no' + required: false + recursive: + description: + - Recurse into directories. + choices: [ 'yes', 'no' ] + default: the value of the archive option + required: false + links: + description: + - Copy symlinks as symlinks. + choices: [ 'yes', 'no' ] + default: the value of the archive option + required: false + perms: + description: + - Preserve permissions. + choices: [ 'yes', 'no' ] + default: the value of the archive option + required: false + times: + description: + - Preserve modification times + choices: [ 'yes', 'no' ] + default: the value of the archive option + required: false + owner: + description: + - Preserve owner (super user only) + choices: [ 'yes', 'no' ] + default: the value of the archive option + required: false + group: + description: + - Preserve group + choices: [ 'yes', 'no' ] + default: the value of the archive option + required: false rsync_path: description: - Specify the rsync command to run on the remote machine. See C(--rsync-path) on the rsync man page. @@ -54,9 +102,18 @@ author: Timothy Appnel ''' EXAMPLES = ''' -# Synchronization of src on the control machien to dest on the remote hosts +# Synchronization of src on the control machine to dest on the remote hosts synchronize: src=some/relative/path dest=/some/absolute/path +# Synchronization without any --archive options enabled +synchronize: src=some/relative/path dest=/some/absolute/path archive=no + +# Synchronization with --archive options enabled except for --recursive +synchronize: src=some/relative/path dest=/some/absolute/path recursive=no + +# Synchronization without --archive options enabled except use --links +synchronize: src=some/relative/path dest=/some/absolute/path archive=no links=yes + # Synchronization of two paths both on the control machine local_action: synchronize src=some/relative/path dest=/some/absolute/path @@ -86,7 +143,7 @@ def main(): private_key = dict(default=None), rsync_path = dict(default=None), archive = dict(default='yes', type='bool'), - dirs = dict(type='bool'), + dirs = dict(default='no', type='bool'), recursive = dict(type='bool'), links = dict(type='bool'), perms = dict(type='bool'), From cbae9c913eb5092395c515dcc4d5bf1feee8f8fe Mon Sep 17 00:00:00 2001 From: Timothy Appnel Date: Sat, 19 Oct 2013 22:39:25 -0400 Subject: [PATCH 10/10] synchronize module src and dest handles template markers. --- lib/ansible/runner/action_plugins/synchronize.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/ansible/runner/action_plugins/synchronize.py b/lib/ansible/runner/action_plugins/synchronize.py index 9439f4350a..a7e9873096 100644 --- a/lib/ansible/runner/action_plugins/synchronize.py +++ b/lib/ansible/runner/action_plugins/synchronize.py @@ -20,6 +20,7 @@ import os.path from ansible import utils from ansible.runner.return_data import ReturnData +import ansible.utils.template as template class ActionModule(object): @@ -57,6 +58,9 @@ class ActionModule(object): src = options.get('src', None) dest = options.get('dest', None) + src = template.template(self.runner.basedir, src, inject) + dest = template.template(self.runner.basedir, dest, inject) + try: options['local_rsync_path'] = inject['ansible_rsync_path'] except KeyError: