@ -37,12 +37,12 @@ description:
files/symlinks/directories. Many other modules support the same options as
files/symlinks/directories. Many other modules support the same options as
the M(file) module - including M(copy), M(template), and M(assemble).
the M(file) module - including M(copy), M(template), and M(assemble).
options:
options:
path :
dest :
description:
description:
- defines the file being managed, unless when used with C(state=link), and then sets the destination to create a symbolic link to using I(src)
- defines the file being managed, unless when used with C(state=link), and then sets the destination to create a symbolic link to using I(src)
required: true
required: true
default: []
default: []
aliases: ['dest', 'name ']
aliases: ['name', 'path ']
state:
state:
description:
description:
- If C(directory), all immediate subdirectories will be created if they
- If C(directory), all immediate subdirectories will be created if they
@ -127,7 +127,7 @@ options:
description:
description:
- 'force the creation of the symlinks in two cases: the source file does
- 'force the creation of the symlinks in two cases: the source file does
not exist (but will appear later); the destination exists and a file (so, we need to unlink the
not exist (but will appear later); the destination exists and a file (so, we need to unlink the
"path " file and create symlink to the "src" file in place of it).'
"dest " file and create symlink to the "src" file in place of it).'
notes:
notes:
- See also M(copy), M(template), M(assemble)
- See also M(copy), M(template), M(assemble)
requirements: [ ]
requirements: [ ]
@ -135,18 +135,18 @@ author: Michael DeHaan
'''
'''
EXAMPLES = '''
EXAMPLES = '''
- file: path =/etc/foo.conf owner=foo group=foo mode=0644
- file: dest =/etc/foo.conf owner=foo group=foo mode=0644
- file: src=/file/to/link/to dest=/path/to/symlink owner=foo group=foo state=link
- file: src=/file/to/link/to dest=/path/to/symlink owner=foo group=foo state=link
'''
'''
def dolink(src, path , state, module):
def dolink(src, dest , state, module):
try:
try:
if state == 'hard':
if state == 'hard':
os.link(src,path )
os.link(src,dest )
else:
else:
os.symlink(src, path )
os.symlink(src, dest )
except OSError, e:
except OSError, e:
module.fail_json(path=path , msg='Error while linking: %s' % str(e))
module.fail_json(dest=dest , msg='Error while linking: %s' % str(e))
def main():
def main():
@ -156,7 +156,7 @@ def main():
module = AnsibleModule(
module = AnsibleModule(
argument_spec = dict(
argument_spec = dict(
state = dict(choices=['file','directory','link','hard','absent'], default='file'),
state = dict(choices=['file','directory','link','hard','absent'], default='file'),
path = dict(aliases=['dest', 'name '], required=True),
dest = dict(aliases=['name', 'path '], required=True),
recurse = dict(default='no', type='bool'),
recurse = dict(default='no', type='bool'),
force = dict(required=False,default=False,type='bool'),
force = dict(required=False,default=False,type='bool'),
diff_peek = dict(default=None),
diff_peek = dict(default=None),
@ -169,20 +169,20 @@ def main():
params = module.params
params = module.params
state = params['state']
state = params['state']
force = params['force']
force = params['force']
params['path'] = path = os.path.expanduser(params['path '])
params['dest'] = dest = os.path.expanduser(params['dest '])
# short-circuit for diff_peek
# short-circuit for diff_peek
if params.get('diff_peek', None) is not None:
if params.get('diff_peek', None) is not None:
appears_binary = False
appears_binary = False
try:
try:
f = open(path )
f = open(dest )
b = f.read(8192)
b = f.read(8192)
f.close()
f.close()
if b.find("\x00") != -1:
if b.find("\x00") != -1:
appears_binary = True
appears_binary = True
except:
except:
pass
pass
module.exit_json(path=path , changed=False, appears_binary=appears_binary)
module.exit_json(dest=dest , changed=False, appears_binary=appears_binary)
# source is both the source of a symlink or an informational passing of the src for a template module
# source is both the source of a symlink or an informational passing of the src for a template module
# or copy module, even if this module never uses it, it is needed to key off some things
# or copy module, even if this module never uses it, it is needed to key off some things
@ -191,24 +191,24 @@ def main():
if src:
if src:
src = os.path.expanduser(src)
src = os.path.expanduser(src)
if src is not None and os.path.isdir(path ) and state != "link":
if src is not None and os.path.isdir(dest ) and state != "link":
params['path'] = path = os.path.join(path , os.path.basename(src))
params['dest'] = dest = os.path.join(dest , os.path.basename(src))
file_args = module.load_file_common_arguments(params)
file_args = module.load_file_common_arguments(params)
if state in ['link','hard'] and (src is None or path is None):
if state in ['link','hard'] and (src is None or dest is None):
module.fail_json(msg='src and dest are required for creating links')
module.fail_json(msg='src and dest are required for creating links')
elif path is None:
elif dest is None:
module.fail_json(msg='path is required')
module.fail_json(msg='path is required')
changed = False
changed = False
prev_state = 'absent'
prev_state = 'absent'
if os.path.lexists(path ):
if os.path.lexists(dest ):
if os.path.islink(path ):
if os.path.islink(dest ):
prev_state = 'link'
prev_state = 'link'
elif os.path.isdir(path ):
elif os.path.isdir(dest ):
prev_state = 'directory'
prev_state = 'directory'
else:
else:
prev_state = 'file'
prev_state = 'file'
@ -216,64 +216,64 @@ def main():
if prev_state != 'absent' and state == 'absent':
if prev_state != 'absent' and state == 'absent':
try:
try:
if prev_state == 'directory':
if prev_state == 'directory':
if os.path.islink(path ):
if os.path.islink(dest ):
if module.check_mode:
if module.check_mode:
module.exit_json(changed=True)
module.exit_json(changed=True)
os.unlink(path )
os.unlink(dest )
else:
else:
try:
try:
if module.check_mode:
if module.check_mode:
module.exit_json(changed=True)
module.exit_json(changed=True)
shutil.rmtree(path , ignore_errors=False)
shutil.rmtree(dest , ignore_errors=False)
except:
except:
module.exit_json(msg="rmtree failed")
module.exit_json(msg="rmtree failed")
else:
else:
if module.check_mode:
if module.check_mode:
module.exit_json(changed=True)
module.exit_json(changed=True)
os.unlink(path )
os.unlink(dest )
except Exception, e:
except Exception, e:
module.fail_json(path=path , msg=str(e))
module.fail_json(dest=dest , msg=str(e))
module.exit_json(path=path , changed=True)
module.exit_json(dest=dest , changed=True)
if prev_state != 'absent' and prev_state != state:
if prev_state != 'absent' and prev_state != state:
if force and prev_state == 'file' and state == 'link':
if force and prev_state == 'file' and state == 'link':
pass
pass
else:
else:
module.fail_json(path=path , msg='refusing to convert between %s and %s for %s' % (prev_state, state, src))
module.fail_json(dest=dest , msg='refusing to convert between %s and %s for %s' % (prev_state, state, src))
if prev_state == 'absent' and state == 'absent':
if prev_state == 'absent' and state == 'absent':
module.exit_json(path=path , changed=False)
module.exit_json(dest=dest , changed=False)
if state == 'file':
if state == 'file':
if prev_state != 'file':
if prev_state != 'file':
module.fail_json(path=path, msg='file (%s) does not exist, use copy or template module to create' % path )
module.fail_json(dest=dest, msg='file (%s) does not exist, use copy or template module to create' % dest )
changed = module.set_file_attributes_if_different(file_args, changed)
changed = module.set_file_attributes_if_different(file_args, changed)
module.exit_json(path=path , changed=changed)
module.exit_json(dest=dest , changed=changed)
elif state == 'directory':
elif state == 'directory':
if prev_state == 'absent':
if prev_state == 'absent':
if module.check_mode:
if module.check_mode:
module.exit_json(changed=True)
module.exit_json(changed=True)
os.makedirs(path )
os.makedirs(dest )
changed = True
changed = True
changed = module.set_directory_attributes_if_different(file_args, changed)
changed = module.set_directory_attributes_if_different(file_args, changed)
recurse = params['recurse']
recurse = params['recurse']
if recurse:
if recurse:
for root,dirs,files in os.walk( file_args['path '] ):
for root,dirs,files in os.walk( file_args['dest '] ):
for dir in dirs:
for dir in dirs:
dirname=os.path.join(root,dir)
dirname=os.path.join(root,dir)
tmp_file_args = file_args.copy()
tmp_file_args = file_args.copy()
tmp_file_args['path ']=dirname
tmp_file_args['dest ']=dirname
changed = module.set_directory_attributes_if_different(tmp_file_args, changed)
changed = module.set_directory_attributes_if_different(tmp_file_args, changed)
for file in files:
for file in files:
filename=os.path.join(root,file)
filename=os.path.join(root,file)
tmp_file_args = file_args.copy()
tmp_file_args = file_args.copy()
tmp_file_args['path ']=filename
tmp_file_args['dest ']=filename
changed = module.set_file_attributes_if_different(tmp_file_args, changed)
changed = module.set_file_attributes_if_different(tmp_file_args, changed)
module.exit_json(path=path , changed=changed)
module.exit_json(dest=dest , changed=changed)
elif state in ['link','hard']:
elif state in ['link','hard']:
@ -283,46 +283,46 @@ def main():
module.fail_json(msg="absolute paths are required")
module.fail_json(msg="absolute paths are required")
if not os.path.exists(abs_src) and not force:
if not os.path.exists(abs_src) and not force:
module.fail_json(path=path , src=src, msg='src file does not exist')
module.fail_json(dest=dest , src=src, msg='src file does not exist')
if prev_state == 'absent':
if prev_state == 'absent':
if module.check_mode:
if module.check_mode:
module.exit_json(changed=True)
module.exit_json(changed=True)
dolink(src, path , state, module)
dolink(src, dest , state, module)
changed = True
changed = True
elif prev_state == 'link':
elif prev_state == 'link':
old_src = os.readlink(path )
old_src = os.readlink(dest )
if not os.path.isabs(old_src):
if not os.path.isabs(old_src):
old_src = os.path.join(os.path.dirname(path ), old_src)
old_src = os.path.join(os.path.dirname(dest ), old_src)
if old_src != src:
if old_src != src:
if module.check_mode:
if module.check_mode:
module.exit_json(changed=True)
module.exit_json(changed=True)
os.unlink(path )
os.unlink(dest )
dolink(src, path , state, module)
dolink(src, dest , state, module)
changed = True
changed = True
elif prev_state == 'file':
elif prev_state == 'file':
if not force:
if not force:
module.fail_json(dest=path , src=src, msg='Cannot link, file exists at destination')
module.fail_json(dest=dest , src=src, msg='Cannot link, file exists at destination')
else:
else:
if module.check_mode:
if module.check_mode:
module.exit_json(changed=True)
module.exit_json(changed=True)
os.unlink(path )
os.unlink(dest )
dolink(src, path , state, module)
dolink(src, dest , state, module)
changed = True
changed = True
else:
else:
module.fail_json(dest=path , src=src, msg='unexpected position reached')
module.fail_json(dest=dest , src=src, msg='unexpected position reached')
# set modes owners and context as needed
# set modes owners and context as needed
file_args = module.load_file_common_arguments(module.params)
file_args = module.load_file_common_arguments(module.params)
changed = module.set_context_if_different(path , file_args['secontext'], changed)
changed = module.set_context_if_different(dest , file_args['secontext'], changed)
changed = module.set_owner_if_different(path , file_args['owner'], changed)
changed = module.set_owner_if_different(dest , file_args['owner'], changed)
changed = module.set_group_if_different(path , file_args['group'], changed)
changed = module.set_group_if_different(dest , file_args['group'], changed)
changed = module.set_mode_if_different(path , file_args['mode'], changed)
changed = module.set_mode_if_different(dest , file_args['mode'], changed)
module.exit_json(dest=path , src=src, changed=changed)
module.exit_json(dest=dest , src=src, changed=changed)
module.fail_json(path=path , msg='unexpected position reached')
module.fail_json(dest=dest , msg='unexpected position reached')
# this is magic, see lib/ansible/module_common.py
# this is magic, see lib/ansible/module_common.py
#<<INCLUDE_ANSIBLE_MODULE_COMMON>>
#<<INCLUDE_ANSIBLE_MODULE_COMMON>>