mirror of
				https://github.com/ansible-collections/community.general.git
				synced 2024-09-14 20:13:21 +02:00 
			
		
		
		
	- added terse syntax to modules.rst - added description of special variables to template module
		
			
				
	
	
		
			250 lines
		
	
	
	
		
			8.2 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			250 lines
		
	
	
	
		
			8.2 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
| #!/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
 | |
| short_description: Sets attributes of files
 | |
| description: 
 | |
|      - Sets attributes of files, symlinks, and directories, or removes
 | |
|        files/symlinks/directories. Many other modules support the same options as
 | |
|        the file module - including M(copy), M(template), and M(assmeble).
 | |
| options:
 | |
|   path:
 | |
|     description:
 | |
|       - defines the file being managed, unless when used with I(state=link), and then sets the destination to create a symbolic link to using I(src)
 | |
|     required: true
 | |
|     default: []
 | |
|     aliases: []
 | |
|   state:
 | |
|     description:
 | |
|       - If C(directory), all immediate subdirectories will be created if they
 | |
|         do not exist. 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. If C(absent),
 | |
|         directories will be recursively deleted, and files or symlinks will be
 | |
|         unlinked.
 | |
|     required: false
 | |
|     default: file
 | |
|     choices: [ file, link, directory, absent ]
 | |
|   mode:
 | |
|     required: false
 | |
|     default: null
 | |
|     choices: []
 | |
|     description:
 | |
|       - mode the file or directory should be, such as 0644 as would be fed to
 | |
|   owner:
 | |
|     required: false
 | |
|     default: null
 | |
|     choices: []
 | |
|     description:
 | |
|       - name of the user that should own the file/directory, as would be fed to I(chown)
 | |
|   group:
 | |
|     required: false
 | |
|     default: null
 | |
|     choices: []
 | |
|     description:
 | |
|       - name of the group that should own the file/directory, as would be fed to I(chown)
 | |
|   src:
 | |
|     required: false
 | |
|     default: null
 | |
|     choices: []
 | |
|     description:
 | |
|       - path of the file to link to (applies only to C(state=link)).
 | |
|   seuser:
 | |
|     required: false
 | |
|     default: null
 | |
|     choices: []
 | |
|     description:
 | |
|       - user part of SELinux file context. Will default to system policy, if
 | |
|         applicable. If set to C(_default), it will use the C(user) portion of the
 | |
|         the policy if available
 | |
|   serole:
 | |
|     required: false
 | |
|     default: null
 | |
|     choices: []
 | |
|     description:
 | |
|       - role part of SELinux file context, C(_default) feature works as for I(seuser).
 | |
|   setype:
 | |
|     required: false
 | |
|     default: null
 | |
|     choices: []
 | |
|     description:
 | |
|       - type part of SELinux file context, C(_default) feature works as for I(seuser).
 | |
|   selevel:
 | |
|     required: false
 | |
|     default: "s0"
 | |
|     choices: []
 | |
|     description:
 | |
|       - level part of the SELinux file context. This is the MLS/MCS attribute,
 | |
|         sometimes known as the C(range). C(_default) feature works as for
 | |
|         I(seuser).
 | |
|   context:
 | |
|     required: false
 | |
|     default: null
 | |
|     choices: [ "default" ]
 | |
|     description:
 | |
|       - accepts only C(default) as value. This will restore a file's SELinux context
 | |
|         in the policy. Does nothing if no default value is available.
 | |
| examples:
 | |
|    - code: "file: path=/etc/foo.conf owner=foo group=foo mode=0644"
 | |
|      description: Example from Ansible Playbooks
 | |
|    - code: "file: src=/file/to/link/to dest=/path/to/symlink owner=foo group=foo state=link"
 | |
| notes:
 | |
|     - See also M(copy), M(template), M(assemble)
 | |
| requirements: [ ]
 | |
| author: Michael DeHaan
 | |
| '''
 | |
| 
 | |
| def main():
 | |
| 
 | |
|     # FIXME: pass this around, should not use global
 | |
|     global module
 | |
| 
 | |
|     module = AnsibleModule(
 | |
|         check_invalid_arguments = False,
 | |
|         argument_spec = dict(
 | |
|             state = dict(choices=['file','directory','link','absent'], default='file'),
 | |
|             path  = dict(aliases=['dest', 'name'], required=True),
 | |
|         ),
 | |
|         add_file_common_args=True
 | |
|     )
 | |
| 
 | |
|     params = module.params
 | |
|     state  = params['state']
 | |
|     path   = os.path.expanduser(params['path'])
 | |
| 
 | |
|     # 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
 | |
| 
 | |
|     src = params.get('src', None)
 | |
|     if src:
 | |
|         src = os.path.expanduser(src)
 | |
| 
 | |
|     if src is not None and os.path.isdir(path) and state != "link":
 | |
|         params['path'] = path = os.path.join(path, os.path.basename(src))
 | |
| 
 | |
|     file_args = module.load_file_common_arguments(params)
 | |
| 
 | |
|     if state == 'link' and (src is None or path is None):
 | |
|         module.fail_json(msg='src and dest are required for "link" state')
 | |
|     elif path is None:
 | |
|         module.fail_json(msg='path is required')
 | |
| 
 | |
|     changed = False
 | |
| 
 | |
|     prev_state = 'absent'
 | |
| 
 | |
|     if os.path.lexists(path):
 | |
|         if os.path.islink(path):
 | |
|             prev_state = 'link'
 | |
|         elif os.path.isdir(path):
 | |
|             prev_state = 'directory'
 | |
|         else:
 | |
|             prev_state = 'file'
 | |
| 
 | |
|     if prev_state != 'absent' and state == 'absent':
 | |
|         try:
 | |
|             if prev_state == 'directory':
 | |
|                 if os.path.islink(path):
 | |
|                     os.unlink(path)
 | |
|                 else:
 | |
|                     try:
 | |
|                         shutil.rmtree(path, ignore_errors=False)
 | |
|                     except:
 | |
|                         module.exit_json(msg="rmtree failed")
 | |
|             else:
 | |
|                 os.unlink(path)
 | |
|         except Exception, e:
 | |
|             module.fail_json(path=path, msg=str(e))
 | |
|         module.exit_json(path=path, changed=True)
 | |
| 
 | |
|     if prev_state != 'absent' and prev_state != state:
 | |
|         module.fail_json(path=path, msg='refusing to convert between %s and %s for %s' % (prev_state, state, src))
 | |
| 
 | |
|     if prev_state == 'absent' and state == 'absent':
 | |
|         module.exit_json(path=path, changed=False)
 | |
| 
 | |
|     if 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) 
 | |
| 
 | |
|         changed = module.set_file_attributes_if_different(file_args, changed)
 | |
|         module.exit_json(path=path, changed=changed)
 | |
| 
 | |
|     elif state == 'directory':
 | |
| 
 | |
|         if prev_state == 'absent':
 | |
|             os.makedirs(path)
 | |
|             changed = True
 | |
| 
 | |
|         changed = module.set_directory_attributes_if_different(file_args, changed)
 | |
|         module.exit_json(path=path, changed=changed)
 | |
| 
 | |
|     elif state == 'link':
 | |
| 
 | |
|         if os.path.isabs(src):
 | |
|             abs_src = src
 | |
|         else:
 | |
|             module.fail_json(msg="absolute paths are required")
 | |
|         if not os.path.exists(abs_src):
 | |
|             module.fail_json(path=path, src=src, msg='src file does not exist')
 | |
| 
 | |
|         if prev_state == 'absent':
 | |
|             os.symlink(src, path)
 | |
|             changed = True
 | |
|         elif prev_state == 'link':
 | |
|             old_src = os.readlink(path)
 | |
|             if not os.path.isabs(old_src):
 | |
|                 old_src = os.path.join(os.path.dirname(path), old_src)
 | |
|             if old_src != src:
 | |
|                 os.unlink(path)
 | |
|                 os.symlink(src, path)
 | |
|                 changed = True
 | |
|         else:
 | |
|             module.fail_json(dest=path, src=src, msg='unexpected position reached')
 | |
| 
 | |
|         # set modes owners and context as needed
 | |
| 
 | |
|         file_args = module.load_file_common_arguments(module.params)
 | |
|         changed = module.set_context_if_different(path, file_args['secontext'], changed)
 | |
|         changed = module.set_owner_if_different(path, file_args['owner'], changed)
 | |
|         changed = module.set_group_if_different(path, file_args['group'], changed)
 | |
|         changed = module.set_mode_if_different(path, file_args['mode'], changed)
 | |
| 
 | |
|         module.exit_json(dest=path, src=src, changed=changed)
 | |
| 
 | |
|     module.fail_json(path=path, msg='unexpected position reached')
 | |
| 
 | |
| # this is magic, see lib/ansible/module_common.py
 | |
| #<<INCLUDE_ANSIBLE_MODULE_COMMON>>
 | |
| main()
 | |
| 
 |