1
0
Fork 0
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:
quidame 2020-06-10 18:01:16 +00:00 committed by GitHub
parent e47da0f512
commit 8635cd84d4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 1085 additions and 0 deletions

View file

@ -0,0 +1 @@
./system/dpkg_divert.py

View 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()

View file

@ -0,0 +1,5 @@
shippable/posix/group4
skip/aix
skip/osx
skip/rhel
skip/freebsd

View file

@ -0,0 +1,4 @@
---
- name: "include tasks for Debian family"
include_tasks: prepare.yml
when: ansible_pkg_mgr == "apt"

View 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

View 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

View 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