|
- #!/usr/bin/python -tt
-
- # (c) 2012, Luis Alberto Perez Lazaro <luisperlazaro@gmail.com>
- #
- # This module 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.
- #
- # This software 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 this software. If not, see <http://www.gnu.org/licenses/>.
- #
-
- DOCUMENTATION = '''
- ---
- module: patch
- author: Luis Alberto Perez Lazaro
- version_added: 0.9
- short_description: apply patch files
- description:
- - Apply patch files using the GNU patch tool. Before using this module make sure the patch tool is installed.
- options:
- patchfile:
- required: true
- description:
- - A patch file as accepted by the gnu patch tool
- strip:
- required: true
- aliases: [ p ]
- description:
- - Number that indicates the smallest prefix containing leading slashes that
- will be stripped from each file name found in the patch file. For more information
- see the strip parameter of the gnu patch tool.
- basedir:
- required: true
- description:
- - base directory in which the patch file will be applied
- examples:
- - code: "patch: patchfile=/tmp/critical.patch strip=1 basedir=/usr/share/pyshared/paramiko"
- description: Example git checkout from Ansible Playbooks
- '''
-
- def _run(args):
- cmd = subprocess.Popen(args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- out, err = cmd.communicate()
- rc = cmd.returncode
- return (rc, out, err)
-
- def _is_already_applied(patch_file, strip):
- reverse_cmd = "patch -s -R -N -p%s --dry-run < %s" % (strip, patch_file)
- (rc, _, _) = _run(reverse_cmd)
- return rc == 0
-
- def _apply_patch(module, patch_file, strip):
- patch_cmd = "patch -s -N -t -r - -p%s < %s" % (strip, patch_file)
- (rc, out, err) = _run(patch_cmd)
- if rc != 0:
- msg = out if not err else err
- module.fail_json(msg=msg)
-
- def _get_params(module):
- patchfile = os.path.expanduser(module.params['patchfile'])
- strip = module.params['strip']
- basedir = module.params['basedir']
-
- if basedir:
- os.chdir(os.path.expanduser(basedir))
-
- if not os.path.exists(patchfile):
- module.fail_json(msg="patchfile %s doesn't exist" % (patchfile))
- if not os.access(patchfile, os.R_OK):
- module.fail_json(msg="patchfile %s not readable" % (patchfile))
-
- if not os.path.exists(basedir):
- module.fail_json(msg="basedir %s doesn't exist" % (patchfile))
-
- try:
- strip = int(strip)
- except Exception:
- module.fail_json(msg="p must be a number")
-
- return patchfile, strip, basedir
-
- # ===========================================
-
- def main():
- module = AnsibleModule(
- argument_spec = dict(
- patchfile=dict(required=True),
- basedir=dict(),
- strip=dict(default=0, aliases=['p'])
- ),
- supports_check_mode = True
- )
- patchfile, strip, basedir = _get_params(module)
-
- changed = False
-
- if module.check_mode:
- if _is_already_applied(patchfile, strip):
- module.exit_json(changed=changed)
- module.exit_json(changed=True)
-
- if not _is_already_applied(patchfile, strip):
- _apply_patch(module, patchfile, strip)
- changed = True
-
- module.exit_json(changed=changed)
-
- # include magic from lib/ansible/module_common.py
- #<<INCLUDE_ANSIBLE_MODULE_COMMON>>
- main()
|