From bb6f90ff6f2408a7c741d2f6c76b44dca2375ae4 Mon Sep 17 00:00:00 2001 From: Martin Krizek Date: Mon, 9 Apr 2018 11:10:42 +0200 Subject: [PATCH] apt: properly set changed for autoremove/autoclean (#38329) --- lib/ansible/modules/packaging/os/apt.py | 15 +++- test/integration/targets/apt/tasks/apt.yml | 12 +--- test/integration/targets/apt/tasks/main.yml | 4 +- test/integration/targets/apt/tasks/repo.yml | 80 +++++++++++++++++++++ 4 files changed, 99 insertions(+), 12 deletions(-) diff --git a/lib/ansible/modules/packaging/os/apt.py b/lib/ansible/modules/packaging/os/apt.py index ec7edda796..57649e23be 100644 --- a/lib/ansible/modules/packaging/os/apt.py +++ b/lib/ansible/modules/packaging/os/apt.py @@ -287,6 +287,12 @@ APT_LISTS_PATH = "/var/lib/apt/lists" APT_UPDATE_SUCCESS_STAMP_PATH = "/var/lib/apt/periodic/update-success-stamp" APT_MARK_INVALID_OP = 'Invalid operation' +CLEAN_OP_CHANGED_STR = dict( + autoremove='The following packages will be REMOVED', + # "Del python3-q 2.4-1 [24 kB]" + autoclean='Del ', +) + HAS_PYTHON_APT = True try: import apt @@ -720,6 +726,10 @@ def remove(m, pkgspec, cache, purge=False, force=False, def cleanup(m, purge=False, force=False, operation=None, dpkg_options=expand_dpkg_options(DPKG_OPTIONS)): + + if operation not in frozenset(['autoremove', 'autoclean']): + raise AssertionError('Expected "autoremove" or "autoclean" cleanup operation, got %s' % operation) + if force: force_yes = '--force-yes' else: @@ -744,7 +754,10 @@ def cleanup(m, purge=False, force=False, operation=None, diff = {} if rc: m.fail_json(msg="'apt-get %s' failed: %s" % (operation, err), stdout=out, stderr=err, rc=rc) - m.exit_json(changed=bool(len(diff)), stdout=out, stderr=err, diff=diff) + + changed = CLEAN_OP_CHANGED_STR[operation] in out + + m.exit_json(changed=changed, stdout=out, stderr=err, diff=diff) def upgrade(m, mode="yes", force=False, default_release=None, diff --git a/test/integration/targets/apt/tasks/apt.yml b/test/integration/targets/apt/tasks/apt.yml index adebd17bdc..0251bea489 100644 --- a/test/integration/targets/apt/tasks/apt.yml +++ b/test/integration/targets/apt/tasks/apt.yml @@ -153,6 +153,9 @@ - "not apt_result.changed" - "apt_result.failed" +- name: autoclean during install + apt: pkg=hello state=present autoclean=yes + # https://github.com/ansible/ansible/issues/23155 - name: create a repo file copy: @@ -210,12 +213,3 @@ with_items: - libcaca-dev - libslang2-dev - -- name: autoclean during install - apt: pkg=hello state=present autoclean=yes - -- name: autoclean - apt: autoclean=yes - -- name: autoremove - apt: autoremove=yes diff --git a/test/integration/targets/apt/tasks/main.yml b/test/integration/targets/apt/tasks/main.yml index 9082f63dd1..d7b7731940 100644 --- a/test/integration/targets/apt/tasks/main.yml +++ b/test/integration/targets/apt/tasks/main.yml @@ -16,8 +16,6 @@ # along with Ansible. If not, see . - block: - - include: 'apt.yml' - - block: - include: 'repo.yml' always: @@ -28,6 +26,8 @@ name: "{{ repodir }}" state: absent + - include: 'apt.yml' + - include: 'apt-multiarch.yml' when: - ansible_userspace_architecture != apt_foreign_arch diff --git a/test/integration/targets/apt/tasks/repo.yml b/test/integration/targets/apt/tasks/repo.yml index b963848ebf..6a5cb66706 100644 --- a/test/integration/targets/apt/tasks/repo.yml +++ b/test/integration/targets/apt/tasks/repo.yml @@ -61,6 +61,86 @@ that: - "dpkg_result is failed" + # https://github.com/ansible/ansible/issues/26298 + - name: Clean up + apt: + name: "{{ item }}" + state: absent + with_items: + - foo + - foobar + + - name: Install foobar, installs foo as a dependency + apt: + name: foobar=1.0.0 + allow_unauthenticated: yes + + - name: Upgrade foobar to a version which does not depend on foo + apt: + upgrade: dist + force: yes # workaround for --allow-unauthenticated used along with upgrade + + - name: autoremove should remove foo + apt: + autoremove: yes + register: autoremove_result + + - name: Check that autoremove correctly reports changed=True + assert: + that: + - "autoremove_result is changed" + + - name: Check foo with dpkg + shell: dpkg-query -l foo + register: dpkg_result + ignore_errors: yes + + - name: Check that foo was removed by autoremove + assert: + that: + - "dpkg_result is failed" + + - name: Nothing to autoremove + apt: + autoremove: yes + register: autoremove_result + + - name: Check that autoremove correctly reports changed=False + assert: + that: + - "autoremove_result is not changed" + + - name: Create a fake .deb file for autoclean to remove + file: + name: /var/cache/apt/archives/python3-q_2.4-1_all.deb + state: touch + + - name: autoclean fake .deb file + apt: + autoclean: yes + register: autoclean_result + + - name: Check if the .deb file exists + stat: + path: /var/cache/apt/archives/python3-q_2.4-1_all.deb + register: stat_result + + - name: Check that autoclean correctly reports changed=True and file was removed + assert: + that: + - "autoclean_result is changed" + - "not stat_result.stat.exists" + + - name: Nothing to autoclean + apt: + autoclean: yes + register: autoclean_result + + - name: Check that autoclean correctly reports changed=False + assert: + that: + - "autoclean_result is not changed" + always: - name: Clean up apt: