2013-09-14 05:20:00 +02:00
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2012-2013, Timothy Appnel <tim@appnel.com>
#
# 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 <http://www.gnu.org/licenses/>.
DOCUMENTATION = '''
- - -
module : synchronize
2013-09-19 06:07:05 +02:00
version_added : " 1.4 "
2013-09-14 05:20:00 +02:00
short_description : Uses rsync to make synchronizing file paths in your playbooks quick and easy .
description :
2015-09-12 22:13:48 +02:00
- C ( synchronize ) is a wrapper around the rsync command , meant to make common tasks with rsync easier . It is run and originates on the local host where Ansible is being run . 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 . C ( synchronize ) does not provide access to the full power of rsync , but does make most invocations easier to follow .
2013-09-14 05:20:00 +02:00
options :
src :
description :
2015-09-12 22:13:48 +02:00
- Path on the source host that will be synchronized to the destination ; The path can be absolute or relative .
2013-09-14 05:20:00 +02:00
required : true
dest :
description :
2015-09-12 22:13:48 +02:00
- Path on the destination host that will be synchronized from the source ; The path can be absolute or relative .
2013-09-14 05:20:00 +02:00
required : true
2013-12-03 20:46:44 +01:00
dest_port :
description :
2015-08-05 21:46:01 +02:00
- Port number for ssh on the destination host . Prior to ansible 2.0 , the ansible_ssh_port inventory var took precedence over this value .
2015-08-05 22:05:59 +02:00
default : Value of ansible_ssh_port for this host , remote_port config setting , or 22 if none of those are set
2013-12-03 20:46:44 +01:00
version_added : " 1.5 "
2013-09-14 05:20:00 +02:00
mode :
description :
2014-10-12 05:11:30 +02:00
- Specify the direction of the synchronization . In push mode the localhost or delegate is the source ; In pull mode the remote host in context is the source .
2013-09-14 05:20:00 +02:00
required : false
choices : [ ' push ' , ' pull ' ]
default : ' push '
2013-09-19 09:09:17 +02:00
archive :
description :
- Mirrors the rsync archive flag , enables recursive , links , perms , times , owner , group flags and - D .
choices : [ ' yes ' , ' no ' ]
default : ' yes '
required : false
2014-03-05 12:17:36 +01:00
checksum :
description :
2014-03-28 19:55:48 +01:00
- Skip based on checksum , rather than mod - time & size ; Note that that " archive " option is still enabled by default - the " checksum " option will not disable it .
2014-03-05 12:17:36 +01:00
choices : [ ' yes ' , ' no ' ]
default : ' no '
required : false
2014-03-17 09:26:44 +01:00
version_added : " 1.6 "
2014-07-12 19:13:04 +02:00
compress :
description :
2014-07-16 00:08:11 +02:00
- Compress file data during the transfer . In most cases , leave this enabled unless it causes problems .
2014-07-12 19:13:04 +02:00
choices : [ ' yes ' , ' no ' ]
default : ' yes '
required : false
version_added : " 1.7 "
2013-11-22 22:59:57 +01:00
existing_only :
description :
- Skip creating new files on receiver .
choices : [ ' yes ' , ' no ' ]
default : ' no '
required : false
2013-12-16 18:20:02 +01:00
version_added : " 1.5 "
2013-09-14 05:20:00 +02:00
delete :
description :
2014-03-26 14:32:55 +01:00
- Delete files that don ' t exist (after transfer, not before) in the C(src) path. This option requires C(recursive=yes).
2013-09-14 05:20:00 +02:00
choices : [ ' yes ' , ' no ' ]
default : ' no '
required : false
2013-09-19 09:09:17 +02:00
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
2013-12-05 20:20:32 +01:00
copy_links :
description :
- Copy symlinks as the item that they point to ( the referent ) is copied , rather than the symlink .
choices : [ ' yes ' , ' no ' ]
default : ' no '
required : false
2013-09-19 09:09:17 +02:00
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
2013-09-14 05:20:00 +02:00
rsync_path :
description :
2015-09-12 22:13:48 +02:00
- Specify the rsync command to run on the remote host . See C ( - - rsync - path ) on the rsync man page .
2013-09-14 05:20:00 +02:00
required : false
2013-11-04 16:57:08 +01:00
rsync_timeout :
description :
- Specify a - - timeout for the rsync command in seconds .
2014-04-28 05:21:54 +02:00
default : 0
2013-11-04 16:57:08 +01:00
required : false
2014-03-20 18:55:02 +01:00
set_remote_user :
description :
- put user @ for the remote paths . If you have a custom ssh config to define the remote user for a host
that does not match the inventory user , you should set this parameter to " no " .
default : yes
2015-04-03 16:42:23 +02:00
use_ssh_args :
description :
- Use the ssh_args specified in ansible . cfg
default : " yes "
choices :
- " yes "
- " no "
2015-04-03 17:27:33 +02:00
version_added : " 2.0 "
2014-03-26 15:55:29 +01:00
rsync_opts :
description :
2014-04-11 17:18:05 +02:00
- Specify additional rsync options by passing in an array .
2014-03-26 15:55:29 +01:00
default :
2014-03-20 18:55:02 +01:00
required : false
2014-04-11 17:04:05 +02:00
version_added : " 1.6 "
2015-02-12 12:25:36 +01:00
partial :
description :
- Tells rsync to keep the partial file which should make a subsequent transfer of the rest of the file much faster .
default : no
required : false
2015-06-25 21:44:08 +02:00
version_added : " 2.0 "
2015-07-19 12:45:31 +02:00
verify_host :
description :
- Verify destination host key .
default : no
required : false
version_added : " 2.0 "
2013-11-04 18:19:31 +01:00
notes :
2015-09-12 22:13:48 +02:00
- rsync must be installed on both the local and remote host .
- For the C ( synchronize ) module , the " local host " is the host ` the synchronize task originates on ` , and the " destination host " is the host ` synchronize is connecting to ` .
2015-09-17 17:30:03 +02:00
- " The user and permissions for the synchronize `src` are those of the user running the Ansible task on the local host, or the `become_user` if `become: yes` is active. synchronize will attempt to escalate privileges to the become_user `on the local host`. "
2015-09-12 22:13:48 +02:00
- The user and permissions for the synchronize ` dest ` are those of the ` remote_user ` on the destination host . If you require permissions ` other ` than those of the remote_user , you must specify this with a sudo command inside the C ( rsync_path ) option in the task ; for example , ` rsync_path = " sudo rsync " ` .
- Expect that dest = ~ / x will be ~ < remote_user > / x even if using sudo .
2013-11-04 18:19:31 +01:00
- Inspect the verbose output to validate the destination user / host / path
are what was expected .
2013-11-25 21:10:59 +01:00
- To exclude files and directories from being synchronized , you may add
C ( . rsync - filter ) files to the source directory .
2014-12-10 20:17:16 +01:00
2015-06-15 21:53:30 +02:00
author : " Timothy Appnel (@tima) "
2013-09-14 05:20:00 +02:00
'''
EXAMPLES = '''
2013-09-19 09:09:17 +02:00
# Synchronization of src on the control machine to dest on the remote hosts
2013-09-14 05:20:00 +02:00
synchronize : src = some / relative / path dest = / some / absolute / path
2013-09-19 09:09:17 +02:00
# 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
2014-03-05 12:17:36 +01:00
# Synchronization with --archive options enabled except for --times, with --checksum option enabled
synchronize : src = some / relative / path dest = / some / absolute / path checksum = yes times = no
2013-09-19 09:09:17 +02:00
# Synchronization without --archive options enabled except use --links
synchronize : src = some / relative / path dest = / some / absolute / path archive = no links = yes
2013-09-14 05:20:00 +02:00
# 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
2014-09-29 23:02:08 +02:00
# Synchronization of src on delegate host to dest on the current inventory host.
2015-09-12 22:13:48 +02:00
# If delegate_to is set to the current inventory host, this can be used to synchronize
2014-09-29 23:02:08 +02:00
# two directories on that host.
2013-09-14 05:20:00 +02:00
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 using an alternate rsync command
2015-09-12 22:13:48 +02:00
# This specific command is granted sudo privileges on the destination
2013-09-14 05:20:00 +02:00
synchronize : src = some / relative / path dest = / some / absolute / path rsync_path = " sudo rsync "
2013-11-25 21:10:59 +01:00
# Example .rsync-filter file in the source directory
- var # exclude any path whose last part is 'var'
- / var # exclude any path starting with 'var' starting at the source directory
+ / var / conf # include /var/conf even though it was previously excluded
2014-03-26 15:55:29 +01:00
# Synchronize passing in extra rsync options
synchronize : src = / tmp / helloworld dest = / var / www / helloword rsync_opts = - - no - motd , - - exclude = . git
2013-09-14 05:20:00 +02:00
'''
def main ( ) :
module = AnsibleModule (
argument_spec = dict (
src = dict ( required = True ) ,
dest = dict ( required = True ) ,
2013-12-03 20:46:44 +01:00
dest_port = dict ( default = 22 ) ,
2013-09-14 05:20:00 +02:00
delete = dict ( default = ' no ' , type = ' bool ' ) ,
private_key = dict ( default = None ) ,
rsync_path = dict ( default = None ) ,
2015-07-27 20:35:21 +02:00
_local_rsync_path = dict ( default = ' rsync ' , type = ' path ' ) ,
2013-09-19 03:17:50 +02:00
archive = dict ( default = ' yes ' , type = ' bool ' ) ,
2014-03-05 12:17:36 +01:00
checksum = dict ( default = ' no ' , type = ' bool ' ) ,
2014-07-12 19:13:04 +02:00
compress = dict ( default = ' yes ' , type = ' bool ' ) ,
2013-11-22 22:59:57 +01:00
existing_only = dict ( default = ' no ' , type = ' bool ' ) ,
2013-09-19 09:09:17 +02:00
dirs = dict ( default = ' no ' , type = ' bool ' ) ,
2013-09-19 03:17:50 +02:00
recursive = dict ( type = ' bool ' ) ,
links = dict ( type = ' bool ' ) ,
2013-12-05 20:20:32 +01:00
copy_links = dict ( type = ' bool ' ) ,
2013-09-19 03:17:50 +02:00
perms = dict ( type = ' bool ' ) ,
times = dict ( type = ' bool ' ) ,
owner = dict ( type = ' bool ' ) ,
group = dict ( type = ' bool ' ) ,
2014-03-20 18:55:02 +01:00
set_remote_user = dict ( default = ' yes ' , type = ' bool ' ) ,
2014-04-28 05:21:54 +02:00
rsync_timeout = dict ( type = ' int ' , default = 0 ) ,
2015-04-03 16:42:23 +02:00
rsync_opts = dict ( type = ' list ' ) ,
ssh_args = dict ( type = ' str ' ) ,
2015-02-12 12:25:36 +01:00
partial = dict ( default = ' no ' , type = ' bool ' ) ,
2015-07-19 12:45:31 +02:00
verify_host = dict ( default = ' no ' , type = ' bool ' ) ,
2015-08-05 20:54:12 +02:00
mode = dict ( default = ' push ' , choices = [ ' push ' , ' pull ' ] ) ,
2013-09-14 05:20:00 +02:00
) ,
supports_check_mode = True
)
2014-05-13 15:05:44 +02:00
source = ' " ' + module . params [ ' src ' ] + ' " '
dest = ' " ' + module . params [ ' dest ' ] + ' " '
2013-12-03 20:46:44 +01:00
dest_port = module . params [ ' dest_port ' ]
2013-09-14 05:20:00 +02:00
delete = module . params [ ' delete ' ]
private_key = module . params [ ' private_key ' ]
rsync_path = module . params [ ' rsync_path ' ]
2015-07-27 20:35:21 +02:00
rsync = module . params . get ( ' _local_rsync_path ' , ' rsync ' )
2013-11-04 16:52:44 +01:00
rsync_timeout = module . params . get ( ' rsync_timeout ' , ' rsync_timeout ' )
2013-09-19 03:17:50 +02:00
archive = module . params [ ' archive ' ]
2014-03-05 12:17:36 +01:00
checksum = module . params [ ' checksum ' ]
2014-07-12 19:13:04 +02:00
compress = module . params [ ' compress ' ]
2013-12-02 15:35:44 +01:00
existing_only = module . params [ ' existing_only ' ]
2013-09-19 03:17:50 +02:00
dirs = module . params [ ' dirs ' ]
2015-02-12 12:25:36 +01:00
partial = module . params [ ' partial ' ]
2013-09-19 03:17:50 +02:00
# the default of these params depends on the value of archive
recursive = module . params [ ' recursive ' ]
links = module . params [ ' links ' ]
2013-12-05 20:20:32 +01:00
copy_links = module . params [ ' copy_links ' ]
2013-09-19 03:17:50 +02:00
perms = module . params [ ' perms ' ]
times = module . params [ ' times ' ]
owner = module . params [ ' owner ' ]
group = module . params [ ' group ' ]
2014-03-26 15:55:29 +01:00
rsync_opts = module . params [ ' rsync_opts ' ]
2015-04-03 16:42:23 +02:00
ssh_args = module . params [ ' ssh_args ' ]
2015-07-19 12:45:31 +02:00
verify_host = module . params [ ' verify_host ' ]
2013-09-19 03:17:50 +02:00
2014-09-28 12:24:47 +02:00
cmd = ' %s --delay-updates -F ' % rsync
2014-07-12 19:13:04 +02:00
if compress :
cmd = cmd + ' --compress '
2014-04-28 05:21:54 +02:00
if rsync_timeout :
cmd = cmd + ' --timeout= %s ' % rsync_timeout
2013-09-14 05:20:00 +02:00
if module . check_mode :
cmd = cmd + ' --dry-run '
if delete :
cmd = cmd + ' --delete-after '
2013-11-22 22:59:57 +01:00
if existing_only :
cmd = cmd + ' --existing '
2014-03-05 12:17:36 +01:00
if checksum :
cmd = cmd + ' --checksum '
2013-09-19 03:17:50 +02:00
if archive :
cmd = cmd + ' --archive '
if recursive is False :
cmd = cmd + ' --no-recursive '
if links is False :
cmd = cmd + ' --no-links '
2013-12-05 20:20:32 +01:00
if copy_links is True :
cmd = cmd + ' --copy-links '
2013-09-19 03:17:50 +02:00
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 '
2013-12-05 20:20:32 +01:00
if copy_links is True :
cmd = cmd + ' --copy-links '
2013-09-19 03:17:50 +02:00
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 '
2013-09-14 05:20:00 +02:00
if private_key is None :
private_key = ' '
else :
private_key = ' -i ' + private_key
2013-12-03 20:46:44 +01:00
2015-07-19 12:45:31 +02:00
ssh_opts = ' -S none '
if not verify_host :
ssh_opts = ' %s -o StrictHostKeyChecking=no ' % ssh_opts
2015-05-04 16:58:05 +02:00
if ssh_args :
2015-07-19 12:45:31 +02:00
ssh_opts = ' %s %s ' % ( ssh_opts , ssh_args )
2015-05-04 16:58:05 +02:00
2013-12-03 20:46:44 +01:00
if dest_port != 22 :
2014-08-18 19:59:00 +02:00
cmd + = " --rsh ' ssh %s %s -o Port= %s ' " % ( private_key , ssh_opts , dest_port )
2013-12-03 20:46:44 +01:00
else :
2014-08-18 19:59:00 +02:00
cmd + = " --rsh ' ssh %s %s ' " % ( private_key , ssh_opts ) # need ssh param
2013-12-03 20:46:44 +01:00
2013-09-14 05:20:00 +02:00
if rsync_path :
2014-04-29 22:46:48 +02:00
cmd = cmd + " --rsync-path= %s " % ( rsync_path )
2014-08-18 19:59:00 +02:00
2014-03-26 15:55:29 +01:00
if rsync_opts :
cmd = cmd + " " + " " . join ( rsync_opts )
2014-08-18 19:59:00 +02:00
2015-02-12 12:25:36 +01:00
if partial :
cmd = cmd + " --partial "
2013-09-19 08:25:33 +02:00
changed_marker = ' <<CHANGED>> '
2013-09-16 06:08:10 +02:00
cmd = cmd + " --out-format= ' " + changed_marker + " %i % n % L ' "
2014-03-10 22:11:24 +01:00
# expand the paths
if ' @ ' not in source :
source = os . path . expanduser ( source )
if ' @ ' not in dest :
dest = os . path . expanduser ( dest )
2013-09-14 05:20:00 +02:00
cmd = ' ' . join ( [ cmd , source , dest ] )
cmdstr = cmd
2013-09-16 06:08:10 +02:00
( rc , out , err ) = module . run_command ( cmd )
if rc :
return module . fail_json ( msg = err , rc = rc , cmd = cmdstr )
2013-09-14 05:20:00 +02:00
else :
2013-09-16 06:08:10 +02:00
changed = changed_marker in out
2014-03-10 17:27:05 +01:00
out_clean = out . replace ( changed_marker , ' ' )
out_lines = out_clean . split ( ' \n ' )
2014-03-28 19:03:24 +01:00
while ' ' in out_lines :
out_lines . remove ( ' ' )
2014-03-10 17:27:05 +01:00
return module . exit_json ( changed = changed , msg = out_clean ,
rc = rc , cmd = cmdstr , stdout_lines = out_lines )
2013-09-14 05:20:00 +02:00
2013-12-02 21:11:23 +01:00
# import module snippets
from ansible . module_utils . basic import *
2013-09-14 05:20:00 +02:00
main ( )