From fdf80690e40a58abd458d57be4cbcc3d985218e7 Mon Sep 17 00:00:00 2001 From: Rick Elrod Date: Tue, 15 Sep 2020 10:36:18 -0500 Subject: [PATCH] [dnf] accumulate update filters (#71726) Change: - Previously when `security: true` and `bugfix: true` were both given, only security updates would get applied. Filters now accumulate so that both get applied in this case. Test Plan: - New integration tests for both check_mode and not. These tests make use of a contrived yum repository which is stored in S3. Tickets: - Fixes #70854 Signed-off-by: Rick Elrod Co-authored-by: Matt Martz Co-authored-by: Matt Martz --- .../70854-dnf-mutually-exclusive-filters.yml | 2 + lib/ansible/modules/dnf.py | 8 +- .../integration/targets/dnf/tasks/filters.yml | 134 ++++++++++++++++++ .../targets/dnf/tasks/filters_check_mode.yml | 110 ++++++++++++++ test/integration/targets/dnf/tasks/main.yml | 12 ++ 5 files changed, 264 insertions(+), 2 deletions(-) create mode 100644 changelogs/fragments/70854-dnf-mutually-exclusive-filters.yml create mode 100644 test/integration/targets/dnf/tasks/filters.yml create mode 100644 test/integration/targets/dnf/tasks/filters_check_mode.yml diff --git a/changelogs/fragments/70854-dnf-mutually-exclusive-filters.yml b/changelogs/fragments/70854-dnf-mutually-exclusive-filters.yml new file mode 100644 index 00000000000..f852dff8f77 --- /dev/null +++ b/changelogs/fragments/70854-dnf-mutually-exclusive-filters.yml @@ -0,0 +1,2 @@ +bugfixes: + - "dnf - it is now possible to specify both ``security: true`` and ``bugfix: true`` to install updates of both types. Previously, only security would get installed if both were true. (https://github.com/ansible/ansible/issues/70854)" diff --git a/lib/ansible/modules/dnf.py b/lib/ansible/modules/dnf.py index 1ede9a04449..3b97ab9675b 100644 --- a/lib/ansible/modules/dnf.py +++ b/lib/ansible/modules/dnf.py @@ -654,12 +654,16 @@ class DnfModule(YumDnf): results=[], rc=1 ) + + filters = [] if self.bugfix: key = {'advisory_type__eq': 'bugfix'} - base._update_security_filters = [base.sack.query().filter(**key)] + filters.append(base.sack.query().filter(**key)) if self.security: key = {'advisory_type__eq': 'security'} - base._update_security_filters = [base.sack.query().filter(**key)] + filters.append(base.sack.query().filter(**key)) + if filters: + base._update_security_filters = filters return base diff --git a/test/integration/targets/dnf/tasks/filters.yml b/test/integration/targets/dnf/tasks/filters.yml new file mode 100644 index 00000000000..d5e9ee906b2 --- /dev/null +++ b/test/integration/targets/dnf/tasks/filters.yml @@ -0,0 +1,134 @@ +# We have a test repo set up with a valid updateinfo.xml which is referenced +# from its repomd.xml. +- block: + - set_fact: + updateinfo_repo: https://ansible-ci-files.s3.amazonaws.com/test/integration/targets/setup_rpm_repo/repo-with-updateinfo + + - name: Install the test repo + yum_repository: + name: test-repo-with-updateinfo + description: test-repo-with-updateinfo + baseurl: "{{ updateinfo_repo }}" + gpgcheck: no + + - name: Install old versions of toaster and oven + dnf: + name: + - "{{ updateinfo_repo }}/toaster-1.2.3.4-1.el8.noarch.rpm" + - "{{ updateinfo_repo }}/oven-1.2.3.4-1.el8.noarch.rpm" + disable_gpg_check: true + + - name: Ask for pending updates + dnf: + name: '*' + state: latest + update_only: true + disable_gpg_check: true + disablerepo: '*' + enablerepo: test-repo-with-updateinfo + register: update_no_filter + + - assert: + that: + - update_no_filter is changed + - '"Installed: toaster-1.2.3.5-1.el8.noarch" in update_no_filter.results' + - '"Installed: oven-1.2.3.5-1.el8.noarch" in update_no_filter.results' + - '"Removed: toaster-1.2.3.4-1.el8.noarch" in update_no_filter.results' + - '"Removed: oven-1.2.3.4-1.el8.noarch" in update_no_filter.results' + + - name: Install old versions of toaster and oven + dnf: + name: + - "{{ updateinfo_repo }}/toaster-1.2.3.4-1.el8.noarch.rpm" + - "{{ updateinfo_repo }}/oven-1.2.3.4-1.el8.noarch.rpm" + allow_downgrade: true + disable_gpg_check: true + + - name: Ask for pending updates with security=true + dnf: + name: '*' + state: latest + update_only: true + disable_gpg_check: true + security: true + disablerepo: '*' + enablerepo: test-repo-with-updateinfo + register: update_security + + - assert: + that: + - update_security is changed + - '"Installed: toaster-1.2.3.5-1.el8.noarch" in update_security.results' + - '"Removed: toaster-1.2.3.4-1.el8.noarch" in update_security.results' + - '"Installed: oven-1.2.3.5-1.el8.noarch" not in update_security.results' + - '"Removed: oven-1.2.3.4-1.el8.noarch" not in update_security.results' + + - name: Install old versions of toaster and oven + dnf: + name: + - "{{ updateinfo_repo }}/toaster-1.2.3.4-1.el8.noarch.rpm" + - "{{ updateinfo_repo }}/oven-1.2.3.4-1.el8.noarch.rpm" + allow_downgrade: true + disable_gpg_check: true + + - name: Ask for pending updates with bugfix=true + dnf: + name: '*' + state: latest + update_only: true + disable_gpg_check: true + bugfix: true + disablerepo: '*' + enablerepo: test-repo-with-updateinfo + register: update_bugfix + + - assert: + that: + - update_bugfix is changed + - '"Installed: toaster-1.2.3.5-1.el8.noarch" not in update_bugfix.results' + - '"Removed: toaster-1.2.3.4-1.el8.noarch" not in update_bugfix.results' + - '"Installed: oven-1.2.3.5-1.el8.noarch" in update_bugfix.results' + - '"Removed: oven-1.2.3.4-1.el8.noarch" in update_bugfix.results' + + - name: Install old versions of toaster and oven + dnf: + name: + - "{{ updateinfo_repo }}/toaster-1.2.3.4-1.el8.noarch.rpm" + - "{{ updateinfo_repo }}/oven-1.2.3.4-1.el8.noarch.rpm" + allow_downgrade: true + disable_gpg_check: true + + - name: Ask for pending updates with bugfix=true and security=true + dnf: + name: '*' + state: latest + update_only: true + disable_gpg_check: true + bugfix: true + security: true + disablerepo: '*' + enablerepo: test-repo-with-updateinfo + register: update_bugfix + + - assert: + that: + - update_bugfix is changed + - '"Installed: toaster-1.2.3.5-1.el8.noarch" in update_bugfix.results' + - '"Removed: toaster-1.2.3.4-1.el8.noarch" in update_bugfix.results' + - '"Installed: oven-1.2.3.5-1.el8.noarch" in update_bugfix.results' + - '"Removed: oven-1.2.3.4-1.el8.noarch" in update_bugfix.results' + + always: + - name: Remove installed packages + dnf: + name: + - toaster + - oven + state: absent + + - name: Remove the repo + yum_repository: + name: test-repo-with-updateinfo + state: absent + tags: + - filters diff --git a/test/integration/targets/dnf/tasks/filters_check_mode.yml b/test/integration/targets/dnf/tasks/filters_check_mode.yml new file mode 100644 index 00000000000..2a30665b94f --- /dev/null +++ b/test/integration/targets/dnf/tasks/filters_check_mode.yml @@ -0,0 +1,110 @@ +# We have a test repo set up with a valid updateinfo.xml which is referenced +# from its repomd.xml. +- block: + - set_fact: + updateinfo_repo: https://ansible-ci-files.s3.amazonaws.com/test/integration/targets/setup_rpm_repo/repo-with-updateinfo + + - name: Install the test repo + yum_repository: + name: test-repo-with-updateinfo + description: test-repo-with-updateinfo + baseurl: "{{ updateinfo_repo }}" + gpgcheck: no + + - name: Install old versions of toaster and oven + dnf: + name: + - "{{ updateinfo_repo }}/toaster-1.2.3.4-1.el8.noarch.rpm" + - "{{ updateinfo_repo }}/oven-1.2.3.4-1.el8.noarch.rpm" + disable_gpg_check: true + + - name: Ask for pending updates (check_mode) + dnf: + name: '*' + state: latest + update_only: true + disable_gpg_check: true + check_mode: true + register: update_no_filter + + - assert: + that: + - update_no_filter is changed + - '"would have if not in check mode" in update_no_filter.msg' + - '"Installed: toaster-1.2.3.5-1.el8.noarch" in update_no_filter.results' + - '"Installed: oven-1.2.3.5-1.el8.noarch" in update_no_filter.results' + - '"Removed: toaster-1.2.3.4-1.el8.noarch" in update_no_filter.results' + - '"Removed: oven-1.2.3.4-1.el8.noarch" in update_no_filter.results' + + - name: Ask for pending updates with security=true (check_mode) + dnf: + name: '*' + state: latest + update_only: true + disable_gpg_check: true + security: true + check_mode: true + register: update_security + + - assert: + that: + - update_security is changed + - '"would have if not in check mode" in update_security.msg' + - '"Installed: toaster-1.2.3.5-1.el8.noarch" in update_security.results' + - '"Removed: toaster-1.2.3.4-1.el8.noarch" in update_security.results' + - '"Installed: oven-1.2.3.5-1.el8.noarch" not in update_security.results' + - '"Removed: oven-1.2.3.4-1.el8.noarch" not in update_security.results' + + - name: Ask for pending updates with bugfix=true (check_mode) + dnf: + name: '*' + state: latest + update_only: true + disable_gpg_check: true + bugfix: true + check_mode: true + register: update_bugfix + + - assert: + that: + - update_bugfix is changed + - '"would have if not in check mode" in update_bugfix.msg' + - '"Installed: toaster-1.2.3.5-1.el8.noarch" not in update_bugfix.results' + - '"Removed: toaster-1.2.3.4-1.el8.noarch" not in update_bugfix.results' + - '"Installed: oven-1.2.3.5-1.el8.noarch" in update_bugfix.results' + - '"Removed: oven-1.2.3.4-1.el8.noarch" in update_bugfix.results' + + - name: Ask for pending updates with bugfix=true and security=true (check_mode) + dnf: + name: '*' + state: latest + update_only: true + disable_gpg_check: true + bugfix: true + security: true + check_mode: true + register: update_bugfix + + - assert: + that: + - update_bugfix is changed + - '"would have if not in check mode" in update_bugfix.msg' + - '"Installed: toaster-1.2.3.5-1.el8.noarch" in update_bugfix.results' + - '"Removed: toaster-1.2.3.4-1.el8.noarch" in update_bugfix.results' + - '"Installed: oven-1.2.3.5-1.el8.noarch" in update_bugfix.results' + - '"Removed: oven-1.2.3.4-1.el8.noarch" in update_bugfix.results' + + always: + - name: Remove installed packages + dnf: + name: + - toaster + - oven + state: absent + + - name: Remove the repo + yum_repository: + name: test-repo-with-updateinfo + state: absent + tags: + - filters diff --git a/test/integration/targets/dnf/tasks/main.yml b/test/integration/targets/dnf/tasks/main.yml index 4825060785f..9fae2d2f836 100644 --- a/test/integration/targets/dnf/tasks/main.yml +++ b/test/integration/targets/dnf/tasks/main.yml @@ -23,6 +23,18 @@ when: (ansible_distribution == 'Fedora' and ansible_distribution_major_version is version('23', '>=')) or (ansible_distribution in ['RedHat', 'CentOS'] and ansible_distribution_major_version is version('8', '>=')) +- include_tasks: filters_check_mode.yml + when: (ansible_distribution == 'Fedora' and ansible_distribution_major_version is version('23', '>=')) or + (ansible_distribution in ['RedHat', 'CentOS'] and ansible_distribution_major_version is version('8', '>=')) + tags: + - filters + +- include_tasks: filters.yml + when: (ansible_distribution == 'Fedora' and ansible_distribution_major_version is version('23', '>=')) or + (ansible_distribution in ['RedHat', 'CentOS'] and ansible_distribution_major_version is version('8', '>=')) + tags: + - filters + - include_tasks: gpg.yml when: (ansible_distribution == 'Fedora' and ansible_distribution_major_version is version('23', '>=')) or (ansible_distribution in ['RedHat', 'CentOS'] and ansible_distribution_major_version is version('8', '>='))