diff options
Diffstat (limited to 'library/files/file')
-rw-r--r-- | library/files/file | 358 |
1 files changed, 0 insertions, 358 deletions
diff --git a/library/files/file b/library/files/file deleted file mode 100644 index ff9feb41ee..0000000000 --- a/library/files/file +++ /dev/null @@ -1,358 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# (c) 2012, Michael DeHaan <michael.dehaan@gmail.com> -# -# This file is part of Ansible -# -# 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/>. - -import shutil -import stat -import grp -import pwd -try: - import selinux - HAVE_SELINUX=True -except ImportError: - HAVE_SELINUX=False - -DOCUMENTATION = ''' ---- -module: file -version_added: "historical" -short_description: Sets attributes of files -extends_documentation_fragment: files -description: - - Sets attributes of files, symlinks, and directories, or removes - files/symlinks/directories. Many other modules support the same options as - the M(file) module - including M(copy), M(template), and M(assemble). -notes: - - See also M(copy), M(template), M(assemble) -requirements: [ ] -author: Michael DeHaan -options: - path: - description: - - 'path to the file being managed. Aliases: I(dest), I(name)' - required: true - default: [] - aliases: ['dest', 'name'] - state: - description: - - If C(directory), all immediate subdirectories will be created if they - do not exist, since 1.7 they will be created with the supplied permissions. - If C(file), the file will NOT be created if it does not exist, see the M(copy) - or M(template) module if you want that behavior. If C(link), the symbolic - link will be created or changed. Use C(hard) for hardlinks. If C(absent), - directories will be recursively deleted, and files or symlinks will be unlinked. - If C(touch) (new in 1.4), an empty file will be created if the c(path) does not - exist, while an existing file or directory will receive updated file access and - modification times (similar to the way `touch` works from the command line). - required: false - default: file - choices: [ file, link, directory, hard, touch, absent ] - src: - required: false - default: null - choices: [] - description: - - path of the file to link to (applies only to C(state=link)). Will accept absolute, - relative and nonexisting paths. Relative paths are not expanded. - recurse: - required: false - default: "no" - choices: [ "yes", "no" ] - version_added: "1.1" - description: - - recursively set the specified file attributes (applies only to state=directory) - force: - required: false - default: "no" - choices: [ "yes", "no" ] - description: - - 'force the creation of the symlinks in two cases: the source file does - not exist (but will appear later); the destination exists and is a file (so, we need to unlink the - "path" file and create symlink to the "src" file in place of it).' -''' - -EXAMPLES = ''' -- file: path=/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=/tmp/{{ item.path }} dest={{ item.dest }} state=link - with_items: - - { path: 'x', dest: 'y' } - - { path: 'z', dest: 'k' } - -# touch a file, using symbolic modes to set the permissions (equivalent to 0644) -- file: path=/etc/foo.conf state=touch mode="u=rw,g=r,o=r" - -# touch the same file, but add/remove some permissions -- file: path=/etc/foo.conf state=touch mode="u+rw,g-wx,o-rwx" - -''' - -def main(): - - module = AnsibleModule( - argument_spec = dict( - state = dict(choices=['file','directory','link','hard','touch','absent'], default=None), - path = dict(aliases=['dest', 'name'], required=True), - original_basename = dict(required=False), # Internal use only, for recursive ops - recurse = dict(default='no', type='bool'), - force = dict(required=False,default=False,type='bool'), - diff_peek = dict(default=None), - validate = dict(required=False, default=None), - src = dict(required=False, default=None), - ), - add_file_common_args=True, - supports_check_mode=True - ) - - params = module.params - state = params['state'] - force = params['force'] - diff_peek = params['diff_peek'] - src = params['src'] - follow = params['follow'] - - # modify source as we later reload and pass, specially relevant when used by other modules. - params['path'] = path = os.path.expanduser(params['path']) - - # short-circuit for diff_peek - if diff_peek is not None: - appears_binary = False - try: - f = open(path) - b = f.read(8192) - f.close() - if "\x00" in b: - appears_binary = True - except: - pass - module.exit_json(path=path, changed=False, appears_binary=appears_binary) - - # Find out current state - prev_state = 'absent' - if os.path.lexists(path): - if os.path.islink(path): - prev_state = 'link' - elif os.path.isdir(path): - prev_state = 'directory' - elif os.stat(path).st_nlink > 1: - prev_state = 'hard' - else: - # could be many other things, but defaulting to file - prev_state = 'file' - - # state should default to file, but since that creates many conflicts, - # default to 'current' when it exists. - if state is None: - if prev_state != 'absent': - state = prev_state - else: - state = 'file' - - # 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 - if src is not None: - src = os.path.expanduser(src) - - # original_basename is used by other modules that depend on file. - if os.path.isdir(path) and state not in ["link", "absent"]: - if params['original_basename']: - basename = params['original_basename'] - else: - basename = os.path.basename(src) - params['path'] = path = os.path.join(path, basename) - else: - if state in ['link','hard']: - if follow: - # use the current target of the link as the source - src = os.readlink(path) - else: - module.fail_json(msg='src and dest are required for creating links') - - # make sure the target path is a directory when we're doing a recursive operation - recurse = params['recurse'] - if recurse and state != 'directory': - module.fail_json(path=path, msg="recurse option requires state to be 'directory'") - - file_args = module.load_file_common_arguments(params) - changed = False - - if state == 'absent': - if state != prev_state: - if not module.check_mode: - if prev_state == 'directory': - try: - shutil.rmtree(path, ignore_errors=False) - except Exception, e: - module.fail_json(msg="rmtree failed: %s" % str(e)) - else: - try: - os.unlink(path) - except Exception, e: - module.fail_json(path=path, msg="unlinking failed: %s " % str(e)) - module.exit_json(path=path, changed=True) - else: - module.exit_json(path=path, changed=False) - - elif state == 'file': - if state != prev_state: - # file is not absent and any other state is a conflict - module.fail_json(path=path, msg='file (%s) is %s, cannot continue' % (path, prev_state)) - - changed = module.set_fs_attributes_if_different(file_args, changed) - module.exit_json(path=path, changed=changed) - - elif state == 'directory': - if prev_state == 'absent': - if module.check_mode: - module.exit_json(changed=True) - changed = True - curpath = '' - # Split the path so we can apply filesystem attributes recursively - # from the root (/) directory for absolute paths or the base path - # of a relative path. We can then walk the appropriate directory - # path to apply attributes. - for dirname in path.strip('/').split('/'): - curpath = '/'.join([curpath, dirname]) - # Remove leading slash if we're creating a relative path - if not os.path.isabs(path): - curpath = curpath.lstrip('/') - if not os.path.exists(curpath): - os.mkdir(curpath) - tmp_file_args = file_args.copy() - tmp_file_args['path']=curpath - changed = module.set_fs_attributes_if_different(tmp_file_args, changed) - - changed = module.set_fs_attributes_if_different(file_args, changed) - - if recurse: - for root,dirs,files in os.walk( file_args['path'] ): - for fsobj in dirs + files: - fsname=os.path.join(root, fsobj) - tmp_file_args = file_args.copy() - tmp_file_args['path']=fsname - changed = module.set_fs_attributes_if_different(tmp_file_args, changed) - - module.exit_json(path=path, changed=changed) - - elif state in ['link','hard']: - - if os.path.isdir(path) and not os.path.islink(path): - relpath = path - else: - relpath = os.path.dirname(path) - - absrc = os.path.join(relpath, src) - if not os.path.exists(absrc) and not force: - module.fail_json(path=path, src=src, msg='src file does not exist, use "force=yes" if you really want to create the link: %s' % absrc) - - if state == 'hard': - if not os.path.isabs(src): - module.fail_json(msg="absolute paths are required") - elif prev_state == 'directory': - if not force: - module.fail_json(path=path, msg='refusing to convert between %s and %s for %s' % (prev_state, state, path)) - elif len(os.listdir(path)) > 0: - # refuse to replace a directory that has files in it - module.fail_json(path=path, msg='the directory %s is not empty, refusing to convert it' % path) - elif prev_state in ['file', 'hard'] and not force: - module.fail_json(path=path, msg='refusing to convert between %s and %s for %s' % (prev_state, state, path)) - - if prev_state == 'absent': - changed = True - elif prev_state == 'link': - old_src = os.readlink(path) - if old_src != src: - changed = True - elif prev_state == 'hard': - if not (state == 'hard' and os.stat(path).st_ino == os.stat(src).st_ino): - changed = True - if not force: - module.fail_json(dest=path, src=src, msg='Cannot link, different hard link exists at destination') - elif prev_state in ['file', 'directory']: - changed = True - if not force: - module.fail_json(dest=path, src=src, msg='Cannot link, %s exists at destination' % prev_state) - else: - module.fail_json(dest=path, src=src, msg='unexpected position reached') - - if changed and not module.check_mode: - if prev_state != 'absent': - # try to replace atomically - tmppath = '/'.join([os.path.dirname(path), ".%s.%s.tmp" % (os.getpid(),time.time())]) - try: - if prev_state == 'directory' and (state == 'hard' or state == 'link'): - os.rmdir(path) - if state == 'hard': - os.link(src,tmppath) - else: - os.symlink(src, tmppath) - os.rename(tmppath, path) - except OSError, e: - if os.path.exists(tmppath): - os.unlink(tmppath) - module.fail_json(path=path, msg='Error while replacing: %s' % str(e)) - else: - try: - if state == 'hard': - os.link(src,path) - else: - os.symlink(src, path) - except OSError, e: - module.fail_json(path=path, msg='Error while linking: %s' % str(e)) - - if module.check_mode and not os.path.exists(path): - module.exit_json(dest=path, src=src, changed=changed) - - changed = module.set_fs_attributes_if_different(file_args, changed) - module.exit_json(dest=path, src=src, changed=changed) - - elif state == 'touch': - if not module.check_mode: - - if prev_state == 'absent': - try: - open(path, 'w').close() - except OSError, e: - module.fail_json(path=path, msg='Error, could not touch target: %s' % str(e)) - elif prev_state in ['file', 'directory']: - try: - os.utime(path, None) - except OSError, e: - module.fail_json(path=path, msg='Error while touching existing target: %s' % str(e)) - else: - module.fail_json(msg='Cannot touch other than files and directories') - try: - module.set_fs_attributes_if_different(file_args, True) - except SystemExit, e: - if e.code: - # We take this to mean that fail_json() was called from - # somewhere in basic.py - if prev_state == 'absent': - # If we just created the file we can safely remove it - os.remove(path) - raise e - - module.exit_json(dest=path, changed=True) - - module.fail_json(path=path, msg='unexpected position reached') - -# import module snippets -from ansible.module_utils.basic import * -main() - |