mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
New module: dpkg_divert (#417)
* feature: module dpkg_divert + tests * try to skip non-deb linux distrib * use collection namespace in EXAMPLES * skip unsupported OS/distrib in tasks instead * tests: remove unskipped distribs * apply changes suggested by Andersson007 * Remove ANSIBLE_METADATA (no more needed). * Normalize docstrings (capitalize descriptions, fix styling, use yes/no booleans). * fix descriptions * update DOCUMENTATION * Drop field 'version_added' (no more needed). * Add a note about check_mode support. * use list comprehension * support diff mode * Move 'before'/'after' dicts into 'diff' dictionary. * Set 'diversion' as the actual state (or the state that would be reached, when in check mode). * Always return 'diversion' on handled exits (exit_json & fail_json). * enable 'diff' mode in tests, add missing 'become'
This commit is contained in:
parent
e47da0f512
commit
8635cd84d4
7 changed files with 1085 additions and 0 deletions
1
plugins/modules/dpkg_divert.py
Symbolic link
1
plugins/modules/dpkg_divert.py
Symbolic link
|
@ -0,0 +1 @@
|
|||
./system/dpkg_divert.py
|
369
plugins/modules/system/dpkg_divert.py
Normal file
369
plugins/modules/system/dpkg_divert.py
Normal file
|
@ -0,0 +1,369 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright: (c) 2017-2020, Yann Amar <quidame@poivron.org>
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: dpkg_divert
|
||||
short_description: Override a debian package's version of a file
|
||||
author:
|
||||
- quidame (@quidame)
|
||||
description:
|
||||
- A diversion is for C(dpkg) the knowledge that only a given package
|
||||
(or the local administrator) is allowed to install a file at a given
|
||||
location. Other packages shipping their own version of this file will
|
||||
be forced to I(divert) it, i.e. to install it at another location. It
|
||||
allows one to keep changes in a file provided by a debian package by
|
||||
preventing its overwrite at package upgrade.
|
||||
- This module manages diversions of debian packages files using the
|
||||
C(dpkg-divert) commandline tool. It can either create or remove a
|
||||
diversion for a given file, but also update an existing diversion
|
||||
to modify its I(holder) and/or its I(divert) location.
|
||||
options:
|
||||
path:
|
||||
description:
|
||||
- The original and absolute path of the file to be diverted or
|
||||
undiverted. This path is unique, i.e. it is not possible to get
|
||||
two diversions for the same I(path).
|
||||
required: true
|
||||
type: path
|
||||
state:
|
||||
description:
|
||||
- When I(state=absent), remove the diversion of the specified
|
||||
I(path); when I(state=present), create the diversion if it does
|
||||
not exist, or update its package I(holder) or I(divert) location,
|
||||
if it already exists.
|
||||
type: str
|
||||
default: present
|
||||
choices: [absent, present]
|
||||
holder:
|
||||
description:
|
||||
- The name of the package whose copy of file is not diverted, also
|
||||
known as the diversion holder or the package the diversion belongs
|
||||
to.
|
||||
- The actual package does not have to be installed or even to exist
|
||||
for its name to be valid. If not specified, the diversion is hold
|
||||
by 'LOCAL', that is reserved by/for dpkg for local diversions.
|
||||
- This parameter is ignored when I(state=absent).
|
||||
type: str
|
||||
divert:
|
||||
description:
|
||||
- The location where the versions of file will be diverted.
|
||||
- Default is to add suffix C(.distrib) to the file path.
|
||||
- This parameter is ignored when I(state=absent).
|
||||
type: path
|
||||
rename:
|
||||
description:
|
||||
- Actually move the file aside (when I(state=present)) or back (when
|
||||
I(state=absent)), but only when changing the state of the diversion.
|
||||
This parameter has no effect when attempting to add a diversion that
|
||||
already exists or when removing an unexisting one.
|
||||
- Unless I(force=true), renaming fails if the destination file already
|
||||
exists (this lock being a dpkg-divert feature, and bypassing it being
|
||||
a module feature).
|
||||
type: bool
|
||||
default: no
|
||||
force:
|
||||
description:
|
||||
- When I(rename=true) and I(force=true), renaming is performed even if
|
||||
the target of the renaming exists, i.e. the existing contents of the
|
||||
file at this location will be lost.
|
||||
- This parameter is ignored when I(rename=false).
|
||||
type: bool
|
||||
default: no
|
||||
notes:
|
||||
- This module supports I(check_mode) and I(diff).
|
||||
requirements:
|
||||
- dpkg-divert >= 1.15.0 (Debian family)
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
- name: Divert /usr/bin/busybox to /usr/bin/busybox.distrib and keep file in place
|
||||
community.general.dpkg_divert:
|
||||
path: /usr/bin/busybox
|
||||
|
||||
- name: Divert /usr/bin/busybox by package 'branding'
|
||||
community.general.dpkg_divert:
|
||||
path: /usr/bin/busybox
|
||||
holder: branding
|
||||
|
||||
- name: Divert and rename busybox to busybox.dpkg-divert
|
||||
community.general.dpkg_divert:
|
||||
path: /usr/bin/busybox
|
||||
divert: /usr/bin/busybox.dpkg-divert
|
||||
rename: yes
|
||||
|
||||
- name: Remove the busybox diversion and move the diverted file back
|
||||
community.general.dpkg_divert:
|
||||
path: /usr/bin/busybox
|
||||
state: absent
|
||||
rename: yes
|
||||
force: yes
|
||||
'''
|
||||
|
||||
RETURN = r'''
|
||||
commands:
|
||||
description: The dpkg-divert commands ran internally by the module.
|
||||
type: list
|
||||
returned: on_success
|
||||
elements: str
|
||||
sample: |-
|
||||
[
|
||||
"/usr/bin/dpkg-divert --no-rename --remove /etc/foobarrc",
|
||||
"/usr/bin/dpkg-divert --package ansible --no-rename --add /etc/foobarrc"
|
||||
]
|
||||
messages:
|
||||
description: The dpkg-divert relevant messages (stdout or stderr).
|
||||
type: list
|
||||
returned: on_success
|
||||
elements: str
|
||||
sample: |-
|
||||
[
|
||||
"Removing 'local diversion of /etc/foobarrc to /etc/foobarrc.distrib'",
|
||||
"Adding 'diversion of /etc/foobarrc to /etc/foobarrc.distrib by ansible'"
|
||||
]
|
||||
diversion:
|
||||
description: The status of the diversion after task execution.
|
||||
type: dict
|
||||
returned: always
|
||||
contains:
|
||||
divert:
|
||||
description: The location of the diverted file.
|
||||
type: str
|
||||
holder:
|
||||
description: The package holding the diversion.
|
||||
type: str
|
||||
path:
|
||||
description: The path of the file to divert/undivert.
|
||||
type: str
|
||||
state:
|
||||
description: The state of the diversion.
|
||||
type: str
|
||||
sample: |-
|
||||
{
|
||||
"divert": "/etc/foobarrc.distrib",
|
||||
"holder": "LOCAL",
|
||||
"path": "/etc/foobarrc"
|
||||
"state": "present"
|
||||
}
|
||||
'''
|
||||
|
||||
|
||||
import re
|
||||
import os
|
||||
from distutils.version import LooseVersion
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils._text import to_bytes, to_native
|
||||
|
||||
|
||||
def diversion_state(module, command, path):
|
||||
diversion = dict(path=path, state='absent', divert=None, holder=None)
|
||||
rc, out, err = module.run_command([command, '--listpackage', path], check_rc=True)
|
||||
if out:
|
||||
diversion['state'] = 'present'
|
||||
diversion['holder'] = out.rstrip()
|
||||
rc, out, err = module.run_command([command, '--truename', path], check_rc=True)
|
||||
diversion['divert'] = out.rstrip()
|
||||
return diversion
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
path=dict(required=True, type='path'),
|
||||
state=dict(required=False, type='str', default='present', choices=['absent', 'present']),
|
||||
holder=dict(required=False, type='str'),
|
||||
divert=dict(required=False, type='path'),
|
||||
rename=dict(required=False, type='bool', default=False),
|
||||
force=dict(required=False, type='bool', default=False),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
path = module.params['path']
|
||||
state = module.params['state']
|
||||
holder = module.params['holder']
|
||||
divert = module.params['divert']
|
||||
rename = module.params['rename']
|
||||
force = module.params['force']
|
||||
|
||||
diversion_wanted = dict(path=path, state=state)
|
||||
changed = False
|
||||
|
||||
DPKG_DIVERT = module.get_bin_path('dpkg-divert', required=True)
|
||||
MAINCOMMAND = [DPKG_DIVERT]
|
||||
|
||||
# Option --listpackage is needed and comes with 1.15.0
|
||||
rc, stdout, stderr = module.run_command([DPKG_DIVERT, '--version'], check_rc=True)
|
||||
[current_version] = [x for x in stdout.splitlines()[0].split() if re.match('^[0-9]+[.][0-9]', x)]
|
||||
if LooseVersion(current_version) < LooseVersion("1.15.0"):
|
||||
module.fail_json(msg="Unsupported dpkg version (<1.15.0).")
|
||||
no_rename_is_supported = (LooseVersion(current_version) >= LooseVersion("1.19.1"))
|
||||
|
||||
b_path = to_bytes(path, errors='surrogate_or_strict')
|
||||
path_exists = os.path.exists(b_path)
|
||||
# Used for things not doable with a single dpkg-divert command (as forced
|
||||
# renaming of files, and diversion's 'holder' or 'divert' updates).
|
||||
target_exists = False
|
||||
truename_exists = False
|
||||
|
||||
diversion_before = diversion_state(module, DPKG_DIVERT, path)
|
||||
if diversion_before['state'] == 'present':
|
||||
b_divert = to_bytes(diversion_before['divert'], errors='surrogate_or_strict')
|
||||
truename_exists = os.path.exists(b_divert)
|
||||
|
||||
# Append options as requested in the task parameters, but ignore some of
|
||||
# them when removing the diversion.
|
||||
if rename:
|
||||
MAINCOMMAND.append('--rename')
|
||||
elif no_rename_is_supported:
|
||||
MAINCOMMAND.append('--no-rename')
|
||||
|
||||
if state == 'present':
|
||||
if holder and holder != 'LOCAL':
|
||||
MAINCOMMAND.extend(['--package', holder])
|
||||
diversion_wanted['holder'] = holder
|
||||
else:
|
||||
MAINCOMMAND.append('--local')
|
||||
diversion_wanted['holder'] = 'LOCAL'
|
||||
|
||||
if divert:
|
||||
MAINCOMMAND.extend(['--divert', divert])
|
||||
target = divert
|
||||
else:
|
||||
target = '%s.distrib' % path
|
||||
|
||||
MAINCOMMAND.extend(['--add', path])
|
||||
diversion_wanted['divert'] = target
|
||||
b_target = to_bytes(target, errors='surrogate_or_strict')
|
||||
target_exists = os.path.exists(b_target)
|
||||
|
||||
else:
|
||||
MAINCOMMAND.extend(['--remove', path])
|
||||
diversion_wanted['divert'] = None
|
||||
diversion_wanted['holder'] = None
|
||||
|
||||
# Start to populate the returned objects.
|
||||
diversion = diversion_before.copy()
|
||||
maincommand = ' '.join(MAINCOMMAND)
|
||||
commands = [maincommand]
|
||||
|
||||
if module.check_mode or diversion_wanted == diversion_before:
|
||||
MAINCOMMAND.insert(1, '--test')
|
||||
diversion_after = diversion_wanted
|
||||
|
||||
# Just try and see
|
||||
rc, stdout, stderr = module.run_command(MAINCOMMAND)
|
||||
|
||||
if rc == 0:
|
||||
messages = [stdout.rstrip()]
|
||||
|
||||
# else... cases of failure with dpkg-divert are:
|
||||
# - The diversion does not belong to the same package (or LOCAL)
|
||||
# - The divert filename is not the same (e.g. path.distrib != path.divert)
|
||||
# - The renaming is forbidden by dpkg-divert (i.e. both the file and the
|
||||
# diverted file exist)
|
||||
|
||||
elif state != diversion_before['state']:
|
||||
# There should be no case with 'divert' and 'holder' when creating the
|
||||
# diversion from none, and they're ignored when removing the diversion.
|
||||
# So this is all about renaming...
|
||||
if rename and path_exists and (
|
||||
(state == 'absent' and truename_exists) or
|
||||
(state == 'present' and target_exists)):
|
||||
if not force:
|
||||
msg = "Set 'force' param to True to force renaming of files."
|
||||
module.fail_json(changed=changed, cmd=maincommand, rc=rc, msg=msg,
|
||||
stderr=stderr, stdout=stdout, diversion=diversion)
|
||||
else:
|
||||
msg = "Unexpected error while changing state of the diversion."
|
||||
module.fail_json(changed=changed, cmd=maincommand, rc=rc, msg=msg,
|
||||
stderr=stderr, stdout=stdout, diversion=diversion)
|
||||
|
||||
to_remove = path
|
||||
if state == 'present':
|
||||
to_remove = target
|
||||
|
||||
if not module.check_mode:
|
||||
try:
|
||||
b_remove = to_bytes(to_remove, errors='surrogate_or_strict')
|
||||
os.unlink(b_remove)
|
||||
except OSError as e:
|
||||
msg = 'Failed to remove %s: %s' % (to_remove, to_native(e))
|
||||
module.fail_json(changed=changed, cmd=maincommand, rc=rc, msg=msg,
|
||||
stderr=stderr, stdout=stdout, diversion=diversion)
|
||||
rc, stdout, stderr = module.run_command(MAINCOMMAND, check_rc=True)
|
||||
|
||||
messages = [stdout.rstrip()]
|
||||
|
||||
# The situation is that we want to modify the settings (holder or divert)
|
||||
# of an existing diversion. dpkg-divert does not handle this, and we have
|
||||
# to remove the existing diversion first, and then set a new one.
|
||||
else:
|
||||
RMDIVERSION = [DPKG_DIVERT, '--remove', path]
|
||||
if no_rename_is_supported:
|
||||
RMDIVERSION.insert(1, '--no-rename')
|
||||
rmdiversion = ' '.join(RMDIVERSION)
|
||||
|
||||
if module.check_mode:
|
||||
RMDIVERSION.insert(1, '--test')
|
||||
|
||||
if rename:
|
||||
MAINCOMMAND.remove('--rename')
|
||||
if no_rename_is_supported:
|
||||
MAINCOMMAND.insert(1, '--no-rename')
|
||||
maincommand = ' '.join(MAINCOMMAND)
|
||||
|
||||
commands = [rmdiversion, maincommand]
|
||||
rc, rmdout, rmderr = module.run_command(RMDIVERSION, check_rc=True)
|
||||
|
||||
if module.check_mode:
|
||||
messages = [rmdout.rstrip(), 'Running in check mode']
|
||||
else:
|
||||
rc, stdout, stderr = module.run_command(MAINCOMMAND, check_rc=True)
|
||||
messages = [rmdout.rstrip(), stdout.rstrip()]
|
||||
|
||||
# Avoid if possible to orphan files (i.e. to dereference them in diversion
|
||||
# database but let them in place), but do not make renaming issues fatal.
|
||||
# BTW, this module is not about state of files involved in the diversion.
|
||||
old = diversion_before['divert']
|
||||
new = diversion_wanted['divert']
|
||||
if new != old:
|
||||
b_old = to_bytes(old, errors='surrogate_or_strict')
|
||||
b_new = to_bytes(new, errors='surrogate_or_strict')
|
||||
if os.path.exists(b_old) and not os.path.exists(b_new):
|
||||
try:
|
||||
os.rename(b_old, b_new)
|
||||
except OSError as e:
|
||||
pass
|
||||
|
||||
if not module.check_mode:
|
||||
diversion_after = diversion_state(module, DPKG_DIVERT, path)
|
||||
|
||||
diversion = diversion_after.copy()
|
||||
diff = dict()
|
||||
if module._diff:
|
||||
diff['before'] = diversion_before
|
||||
diff['after'] = diversion_after
|
||||
|
||||
if diversion_after != diversion_before:
|
||||
changed = True
|
||||
|
||||
if diversion_after == diversion_wanted:
|
||||
module.exit_json(changed=changed, diversion=diversion,
|
||||
commands=commands, messages=messages, diff=diff)
|
||||
else:
|
||||
msg = "Unexpected error: see stdout and stderr for details."
|
||||
module.fail_json(changed=changed, cmd=maincommand, rc=rc, msg=msg,
|
||||
stderr=stderr, stdout=stdout, diversion=diversion)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
5
tests/integration/targets/dpkg_divert/aliases
Normal file
5
tests/integration/targets/dpkg_divert/aliases
Normal file
|
@ -0,0 +1,5 @@
|
|||
shippable/posix/group4
|
||||
skip/aix
|
||||
skip/osx
|
||||
skip/rhel
|
||||
skip/freebsd
|
4
tests/integration/targets/dpkg_divert/tasks/main.yml
Normal file
4
tests/integration/targets/dpkg_divert/tasks/main.yml
Normal file
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
- name: "include tasks for Debian family"
|
||||
include_tasks: prepare.yml
|
||||
when: ansible_pkg_mgr == "apt"
|
39
tests/integration/targets/dpkg_divert/tasks/prepare.yml
Normal file
39
tests/integration/targets/dpkg_divert/tasks/prepare.yml
Normal file
|
@ -0,0 +1,39 @@
|
|||
---
|
||||
- name: "set variables for the entire playbook"
|
||||
set_fact:
|
||||
foobarrc: "{{ foobarrc }}"
|
||||
foobarrc_ansible: "{{ foobarrc }}.ansible"
|
||||
foobarrc_distrib: "{{ foobarrc }}.distrib"
|
||||
foobarrc_oldtext: "# foobar configuration file\n# Please refer to the documentation for details\n"
|
||||
foobarrc_oldsha1: "e1c54c36d2fd1b8d67d1826e49b95ac8c0f24c0a"
|
||||
foobarrc_newtext: "# Custom foobar configuration file\nFOO=bar\nBAR=foo"
|
||||
foobarrc_newsha1: "3fe6c890519fb48e27c1b0e3e37afb11357d5cac"
|
||||
vars:
|
||||
foobarrc: "/etc/foobarrc"
|
||||
|
||||
- name: "remove foobarrc diversion"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
state: absent
|
||||
become: yes
|
||||
|
||||
- name: "remove test files"
|
||||
file:
|
||||
path: "{{ dpkg_divert_item }}"
|
||||
state: absent
|
||||
loop:
|
||||
- "{{ foobarrc_ansible }}"
|
||||
- "{{ foobarrc_distrib }}"
|
||||
loop_control:
|
||||
loop_var: dpkg_divert_item
|
||||
become: yes
|
||||
|
||||
|
||||
- block:
|
||||
- name: "include tasks to perform basic tests (create, remove, update)"
|
||||
include_tasks: tests/01-basic.yml
|
||||
|
||||
- name: "include tasks to perform other tests (rename)"
|
||||
include_tasks: tests/02-rename.yml
|
||||
become: yes
|
||||
diff: yes
|
287
tests/integration/targets/dpkg_divert/tasks/tests/01-basic.yml
Normal file
287
tests/integration/targets/dpkg_divert/tasks/tests/01-basic.yml
Normal file
|
@ -0,0 +1,287 @@
|
|||
---
|
||||
################################################################################
|
||||
# TEST 01: state=present
|
||||
|
||||
- name: "create foobarrc for tests"
|
||||
copy:
|
||||
dest: "{{ foobarrc }}"
|
||||
content: "{{ foobarrc_oldtext }}"
|
||||
|
||||
|
||||
- name: "divert foobarrc (check mode, must report a change)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
state: present
|
||||
register: diversion_0
|
||||
check_mode: true
|
||||
|
||||
- name: "divert foobarrc (must report a change)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
state: present
|
||||
register: diversion_1
|
||||
|
||||
|
||||
- name: "divert foobarrc (must NOT report a change, idempotency)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
state: present
|
||||
register: diversion_2
|
||||
|
||||
- name: "divert foobarrc (check mode, must NOT report a change, idempotency)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
state: present
|
||||
register: diversion_3
|
||||
check_mode: true
|
||||
|
||||
|
||||
# Ensure that 'rename' has no effect when state is not changed
|
||||
|
||||
- name: "divert foobarrc (rename, must NOT report a change, idempotency)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
state: present
|
||||
rename: yes
|
||||
register: diversion_4
|
||||
|
||||
- name: "divert foobarrc (check mode, rename, must NOT report a change, idempotency)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
state: present
|
||||
rename: yes
|
||||
register: diversion_5
|
||||
check_mode: true
|
||||
|
||||
|
||||
# Check results
|
||||
|
||||
- name: "stat foobarrc (must still be there)"
|
||||
stat:
|
||||
path: "{{ foobarrc }}"
|
||||
register: diversion_6
|
||||
|
||||
- name: "stat foobarrc.distrib (must not exist)"
|
||||
stat:
|
||||
path: "{{ foobarrc_distrib }}"
|
||||
register: diversion_7
|
||||
|
||||
- name: "assert that results of test 01 are as expected"
|
||||
assert:
|
||||
that:
|
||||
- diversion_0 is changed
|
||||
- diversion_1 is changed
|
||||
- diversion_2 is not changed
|
||||
- diversion_3 is not changed
|
||||
- diversion_4 is not changed
|
||||
- diversion_5 is not changed
|
||||
- diversion_6.stat.exists
|
||||
- diversion_6.stat.checksum == foobarrc_oldsha1
|
||||
- not diversion_7.stat.exists
|
||||
- diversion_0.diversion == diversion_1.diversion
|
||||
- diversion_2.diversion == diversion_3.diversion
|
||||
- diversion_4.diversion == diversion_5.diversion
|
||||
- diversion_0.commands == diversion_1.commands
|
||||
- diversion_2.commands == diversion_3.commands
|
||||
- diversion_4.commands == diversion_5.commands
|
||||
quiet: yes
|
||||
|
||||
|
||||
################################################################################
|
||||
# TEST 02: state=absent
|
||||
|
||||
- name: "remove diversion for foobarrc (check mode, must report a change)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
state: absent
|
||||
register: diversion_0
|
||||
check_mode: true
|
||||
|
||||
- name: "remove diversion for foobarrc (must report a change)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
state: absent
|
||||
register: diversion_1
|
||||
|
||||
|
||||
- name: "remove diversion for foobarrc (must NOT report a change, idempotency)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
state: absent
|
||||
register: diversion_2
|
||||
|
||||
- name: "remove diversion for foobarrc (check mode, must NOT report a change, idempotency)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
state: absent
|
||||
register: diversion_3
|
||||
check_mode: true
|
||||
|
||||
|
||||
# Check results
|
||||
|
||||
- name: "stat foobarrc (must still be there)"
|
||||
stat:
|
||||
path: "{{ foobarrc }}"
|
||||
register: diversion_4
|
||||
|
||||
- name: "stat foobarrc.distrib (must not exist)"
|
||||
stat:
|
||||
path: "{{ foobarrc_distrib }}"
|
||||
register: diversion_5
|
||||
|
||||
- name: "assert that results of test 02 are as expected"
|
||||
assert:
|
||||
that:
|
||||
- diversion_0 is changed
|
||||
- diversion_1 is changed
|
||||
- diversion_2 is not changed
|
||||
- diversion_3 is not changed
|
||||
- diversion_4.stat.exists
|
||||
- diversion_4.stat.checksum == foobarrc_oldsha1
|
||||
- not diversion_5.stat.exists
|
||||
- diversion_0.diversion == diversion_1.diversion
|
||||
- diversion_2.diversion == diversion_3.diversion
|
||||
- diversion_0.commands == diversion_1.commands
|
||||
- diversion_2.commands == diversion_3.commands
|
||||
quiet: yes
|
||||
|
||||
|
||||
################################################################################
|
||||
# TEST 03: holder=ansible
|
||||
|
||||
- name: "create foobarrc diversion with defaults"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
|
||||
|
||||
- name: "update foobarrc diversion holder (check mode, must report a change)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
holder: "ansible"
|
||||
register: diversion_0
|
||||
check_mode: yes
|
||||
|
||||
- name: "update foobarrc diversion holder (must report a change)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
holder: "ansible"
|
||||
register: diversion_1
|
||||
|
||||
|
||||
- name: "update foobarrc diversion holder (must NOT report a change, idempotency)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
holder: "ansible"
|
||||
register: diversion_2
|
||||
|
||||
- name: "update foobarrc diversion holder (check mode, must NOT report a change, idempotency)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
holder: "ansible"
|
||||
register: diversion_3
|
||||
check_mode: yes
|
||||
|
||||
|
||||
# Check results
|
||||
|
||||
- name: "stat foobarrc (must still be there)"
|
||||
stat:
|
||||
path: "{{ foobarrc }}"
|
||||
register: diversion_4
|
||||
|
||||
- name: "stat foobarrc.distrib (must not exist)"
|
||||
stat:
|
||||
path: "{{ foobarrc_distrib }}"
|
||||
register: diversion_5
|
||||
|
||||
- name: "assert that results of test 03 are as expected"
|
||||
assert:
|
||||
that:
|
||||
- diversion_0 is changed
|
||||
- diversion_1 is changed
|
||||
- diversion_2 is not changed
|
||||
- diversion_3 is not changed
|
||||
- diversion_4.stat.exists
|
||||
- diversion_4.stat.checksum == foobarrc_oldsha1
|
||||
- not diversion_5.stat.exists
|
||||
- diversion_0.diversion == diversion_1.diversion
|
||||
- diversion_2.diversion == diversion_3.diversion
|
||||
- diversion_0.commands == diversion_1.commands
|
||||
- diversion_2.commands == diversion_3.commands
|
||||
quiet: yes
|
||||
|
||||
- name: "remove foobarrc diversion"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
state: absent
|
||||
|
||||
|
||||
################################################################################
|
||||
# TEST 04: divert=/etc/foobarrc.ansible
|
||||
|
||||
- name: "create foobarrc diversion with defaults"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
|
||||
|
||||
- name: "update foobarrc divert path (check mode, must report a change)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
divert: "{{ foobarrc_ansible }}"
|
||||
register: diversion_0
|
||||
check_mode: yes
|
||||
|
||||
- name: "update foobarrc divert path (must report a change)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
divert: "{{ foobarrc_ansible }}"
|
||||
register: diversion_1
|
||||
|
||||
|
||||
- name: "update foobarrc divert path (must NOT report a change, idempotency)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
divert: "{{ foobarrc_ansible }}"
|
||||
register: diversion_2
|
||||
|
||||
- name: "update foobarrc divert path (check mode, must NOT report a change, idempotency)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
divert: "{{ foobarrc_ansible }}"
|
||||
register: diversion_3
|
||||
check_mode: yes
|
||||
|
||||
|
||||
# Check results
|
||||
|
||||
- name: "stat foobarrc (must still be there)"
|
||||
stat:
|
||||
path: "{{ foobarrc }}"
|
||||
register: diversion_4
|
||||
|
||||
- name: "stat foobarrc.ansible (must not exist)"
|
||||
stat:
|
||||
path: "{{ foobarrc_ansible }}"
|
||||
register: diversion_5
|
||||
|
||||
- name: "assert that results of test 04 are as expected"
|
||||
assert:
|
||||
that:
|
||||
- diversion_0 is changed
|
||||
- diversion_1 is changed
|
||||
- diversion_2 is not changed
|
||||
- diversion_3 is not changed
|
||||
- diversion_4.stat.exists
|
||||
- diversion_4.stat.checksum == foobarrc_oldsha1
|
||||
- not diversion_5.stat.exists
|
||||
- diversion_0.diversion == diversion_1.diversion
|
||||
- diversion_2.diversion == diversion_3.diversion
|
||||
- diversion_0.commands == diversion_1.commands
|
||||
- diversion_2.commands == diversion_3.commands
|
||||
quiet: yes
|
||||
|
||||
- name: "remove foobarrc diversion"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
state: absent
|
380
tests/integration/targets/dpkg_divert/tasks/tests/02-rename.yml
Normal file
380
tests/integration/targets/dpkg_divert/tasks/tests/02-rename.yml
Normal file
|
@ -0,0 +1,380 @@
|
|||
---
|
||||
################################################################################
|
||||
# TEST 05: rename=yes, state=present
|
||||
|
||||
- name: "create diversion for foobarrc (check mode, rename, must report a change)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
rename: yes
|
||||
register: diversion_0
|
||||
check_mode: yes
|
||||
|
||||
- name: "create diversion for foobarrc (rename, must report a change)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
rename: yes
|
||||
register: diversion_1
|
||||
|
||||
|
||||
- name: "create diversion for foobarrc (rename, must NOT report a change, idempotency)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
rename: yes
|
||||
register: diversion_2
|
||||
|
||||
- name: "create diversion for foobarrc (check mode, rename, must NOT report a change, idempotency)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
rename: yes
|
||||
register: diversion_3
|
||||
check_mode: yes
|
||||
|
||||
|
||||
# Get results
|
||||
|
||||
- name: "stat foobarrc (must not exist)"
|
||||
stat:
|
||||
path: "{{ foobarrc }}"
|
||||
register: diversion_4
|
||||
|
||||
- name: "stat foobarrc.distrib (must exist)"
|
||||
stat:
|
||||
path: "{{ foobarrc_distrib }}"
|
||||
register: diversion_5
|
||||
|
||||
- name: "assert that results of test 05 are as expected"
|
||||
assert:
|
||||
that:
|
||||
- diversion_0 is changed
|
||||
- diversion_1 is changed
|
||||
- diversion_2 is not changed
|
||||
- diversion_3 is not changed
|
||||
- not diversion_4.stat.exists
|
||||
- diversion_5.stat.exists
|
||||
- diversion_5.stat.checksum == foobarrc_oldsha1
|
||||
- diversion_0.diversion == diversion_1.diversion
|
||||
- diversion_2.diversion == diversion_3.diversion
|
||||
- diversion_0.commands == diversion_1.commands
|
||||
- diversion_2.commands == diversion_3.commands
|
||||
quiet: yes
|
||||
|
||||
|
||||
################################################################################
|
||||
# TEST 06: rename=yes, state=absent
|
||||
|
||||
- name: "remove diversion for foobarrc (check mode, rename, must report a change)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
rename: yes
|
||||
state: absent
|
||||
register: diversion_0
|
||||
check_mode: yes
|
||||
|
||||
- name: "remove diversion for foobarrc (rename, must report a change)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
rename: yes
|
||||
state: absent
|
||||
register: diversion_1
|
||||
|
||||
|
||||
- name: "remove diversion for foobarrc (rename, must NOT report a change, idempotency)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
rename: yes
|
||||
state: absent
|
||||
register: diversion_2
|
||||
|
||||
- name: "remove diversion for foobarrc (check mode, rename, must NOT report a change, idempotency)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
rename: yes
|
||||
state: absent
|
||||
register: diversion_3
|
||||
check_mode: yes
|
||||
|
||||
|
||||
# Check results
|
||||
|
||||
- name: "stat foobarrc (must exist)"
|
||||
stat:
|
||||
path: "{{ foobarrc }}"
|
||||
register: diversion_4
|
||||
|
||||
- name: "stat foobarrc.distrib (must not exist)"
|
||||
stat:
|
||||
path: "{{ foobarrc_distrib }}"
|
||||
register: diversion_5
|
||||
|
||||
- name: "assert that results of test 06 are as expected"
|
||||
assert:
|
||||
that:
|
||||
- diversion_0 is changed
|
||||
- diversion_1 is changed
|
||||
- diversion_2 is not changed
|
||||
- diversion_3 is not changed
|
||||
- diversion_4.stat.exists
|
||||
- diversion_4.stat.checksum == foobarrc_oldsha1
|
||||
- not diversion_5.stat.exists
|
||||
- diversion_0.diversion == diversion_1.diversion
|
||||
- diversion_2.diversion == diversion_3.diversion
|
||||
- diversion_0.commands == diversion_1.commands
|
||||
- diversion_2.commands == diversion_3.commands
|
||||
quiet: yes
|
||||
|
||||
|
||||
################################################################################
|
||||
# TEST 07: rename=yes, force=yes, state=present
|
||||
|
||||
- name: "create foobarrc.distrib for tests"
|
||||
copy:
|
||||
dest: "{{ foobarrc_distrib }}"
|
||||
content: "{{ foobarrc_oldtext }}"
|
||||
|
||||
|
||||
- name: "create diversion for foobarrc (check mode, rename, must fail)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
rename: yes
|
||||
register: diversion_0
|
||||
ignore_errors: yes
|
||||
check_mode: yes
|
||||
|
||||
- name: "create diversion for foobarrc (rename, must fail)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
rename: yes
|
||||
register: diversion_1
|
||||
ignore_errors: yes
|
||||
|
||||
|
||||
- name: "create diversion for foobarrc (check mode, force rename, must report a change)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
rename: yes
|
||||
force: yes
|
||||
register: diversion_2
|
||||
check_mode: yes
|
||||
|
||||
- name: "create diversion for foobarrc (force rename, must report a change)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
rename: yes
|
||||
force: yes
|
||||
register: diversion_3
|
||||
|
||||
|
||||
- name: "create diversion for foobarrc (force rename, must NOT report a change, idempotency)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
rename: yes
|
||||
force: yes
|
||||
register: diversion_4
|
||||
|
||||
- name: "create diversion for foobarrc (check mode, force rename, must NOT report a change, idempotency)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
rename: yes
|
||||
force: yes
|
||||
register: diversion_5
|
||||
check_mode: yes
|
||||
|
||||
|
||||
# Check results
|
||||
|
||||
- name: "stat foobarrc (must not exist)"
|
||||
stat:
|
||||
path: "{{ foobarrc }}"
|
||||
register: diversion_6
|
||||
|
||||
- name: "stat foobarrc.distrib (must exist)"
|
||||
stat:
|
||||
path: "{{ foobarrc_distrib }}"
|
||||
register: diversion_7
|
||||
|
||||
- name: "assert that results of test 07 are as expected"
|
||||
assert:
|
||||
that:
|
||||
- diversion_0 is failed
|
||||
- diversion_1 is failed
|
||||
- diversion_2 is changed
|
||||
- diversion_3 is changed
|
||||
- diversion_4 is not changed
|
||||
- diversion_5 is not changed
|
||||
- not diversion_6.stat.exists
|
||||
- diversion_7.stat.exists
|
||||
- diversion_7.stat.checksum == foobarrc_oldsha1
|
||||
- diversion_0 == diversion_1
|
||||
- diversion_2.diversion == diversion_3.diversion
|
||||
- diversion_4.diversion == diversion_5.diversion
|
||||
- diversion_2.commands == diversion_3.commands
|
||||
- diversion_4.commands == diversion_5.commands
|
||||
quiet: yes
|
||||
|
||||
|
||||
################################################################################
|
||||
# TEST 08: state=present, update an existing divert path
|
||||
|
||||
- name: "create foobarrc with new contents for tests"
|
||||
copy:
|
||||
dest: "{{ foobarrc }}"
|
||||
content: "{{ foobarrc_newtext }}"
|
||||
|
||||
|
||||
- name: "create diversion for foobarrc (check mode, update divert path, must report a change)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
divert: "{{ foobarrc_ansible }}"
|
||||
register: diversion_0
|
||||
check_mode: yes
|
||||
|
||||
- name: "create diversion for foobarrc (update divert path, must report a change)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
divert: "{{ foobarrc_ansible }}"
|
||||
register: diversion_1
|
||||
|
||||
|
||||
- name: "create diversion for foobarrc (update divert path, must NOT report a change, idempotency)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
divert: "{{ foobarrc_ansible }}"
|
||||
register: diversion_2
|
||||
|
||||
- name: "create diversion for foobarrc (check mode, update divert path, must NOT report a change, idempotency)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
divert: "{{ foobarrc_ansible }}"
|
||||
register: diversion_3
|
||||
check_mode: yes
|
||||
|
||||
|
||||
# Check results
|
||||
|
||||
- name: "stat foobarrc (must exist)"
|
||||
stat:
|
||||
path: "{{ foobarrc }}"
|
||||
register: diversion_4
|
||||
|
||||
- name: "stat foobarrc.ansible (must exist)"
|
||||
stat:
|
||||
path: "{{ foobarrc_ansible }}"
|
||||
register: diversion_5
|
||||
|
||||
- name: "stat foobarrc.distrib (must not exist)"
|
||||
stat:
|
||||
path: "{{ foobarrc_distrib }}"
|
||||
register: diversion_6
|
||||
|
||||
- name: "assert that results of test 08 are as expected"
|
||||
assert:
|
||||
that:
|
||||
- diversion_0 is changed
|
||||
- diversion_1 is changed
|
||||
- diversion_2 is not changed
|
||||
- diversion_3 is not changed
|
||||
- diversion_4.stat.exists
|
||||
- diversion_4.stat.checksum == foobarrc_newsha1
|
||||
- diversion_5.stat.exists
|
||||
- diversion_5.stat.checksum == foobarrc_oldsha1
|
||||
- not diversion_6.stat.exists
|
||||
- diversion_0.diversion == diversion_1.diversion
|
||||
- diversion_2.diversion == diversion_3.diversion
|
||||
- diversion_0.commands == diversion_1.commands
|
||||
- diversion_2.commands == diversion_3.commands
|
||||
quiet: yes
|
||||
|
||||
|
||||
################################################################################
|
||||
# TEST 09: rename=yes, force=yes, state=absent
|
||||
|
||||
- name: "remove diversion for foobarrc (check mode, rename, must fail)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
state: absent
|
||||
rename: yes
|
||||
register: diversion_0
|
||||
ignore_errors: yes
|
||||
check_mode: yes
|
||||
|
||||
- name: "remove diversion for foobarrc (rename, must fail)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
state: absent
|
||||
rename: yes
|
||||
register: diversion_1
|
||||
ignore_errors: yes
|
||||
|
||||
|
||||
- name: "remove diversion for foobarrc (check mode, force rename, must report a change)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
state: absent
|
||||
rename: yes
|
||||
force: yes
|
||||
register: diversion_2
|
||||
check_mode: yes
|
||||
|
||||
- name: "remove diversion for foobarrc (force rename, must report a change)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
state: absent
|
||||
rename: yes
|
||||
force: yes
|
||||
register: diversion_3
|
||||
|
||||
|
||||
- name: "remove diversion for foobarrc (force rename, must NOT report a change, idempotency)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
state: absent
|
||||
rename: yes
|
||||
force: yes
|
||||
register: diversion_4
|
||||
|
||||
- name: "remove diversion for foobarrc (check mode, force rename, must NOT report a change, idempotency)"
|
||||
dpkg_divert:
|
||||
path: "{{ foobarrc }}"
|
||||
state: absent
|
||||
rename: yes
|
||||
force: yes
|
||||
register: diversion_5
|
||||
check_mode: yes
|
||||
|
||||
|
||||
# Check results
|
||||
|
||||
- name: "stat foobarrc (must exist)"
|
||||
stat:
|
||||
path: "{{ foobarrc }}"
|
||||
register: diversion_6
|
||||
|
||||
- name: "stat foobarrc.distrib (must not exist)"
|
||||
stat:
|
||||
path: "{{ foobarrc_distrib }}"
|
||||
register: diversion_7
|
||||
|
||||
- name: "stat foobarrc.ansible (must not exist)"
|
||||
stat:
|
||||
path: "{{ foobarrc_ansible }}"
|
||||
register: diversion_8
|
||||
|
||||
- name: "assert that results of test 09 are as expected"
|
||||
assert:
|
||||
that:
|
||||
- diversion_0 is failed
|
||||
- diversion_1 is failed
|
||||
- diversion_2 is changed
|
||||
- diversion_3 is changed
|
||||
- diversion_4 is not changed
|
||||
- diversion_5 is not changed
|
||||
- diversion_6.stat.exists
|
||||
- diversion_6.stat.checksum == foobarrc_oldsha1
|
||||
- not diversion_7.stat.exists
|
||||
- not diversion_8.stat.exists
|
||||
- diversion_0 == diversion_1
|
||||
- diversion_2.diversion == diversion_3.diversion
|
||||
- diversion_4.diversion == diversion_5.diversion
|
||||
- diversion_2.commands == diversion_3.commands
|
||||
- diversion_4.commands == diversion_5.commands
|
||||
quiet: yes
|
Loading…
Reference in a new issue