diff --git a/changelogs/fragments/85254-apt-version-comparison-bugfix.yaml b/changelogs/fragments/85254-apt-version-comparison-bugfix.yaml new file mode 100644 index 00000000000..49b7d1260ee --- /dev/null +++ b/changelogs/fragments/85254-apt-version-comparison-bugfix.yaml @@ -0,0 +1,2 @@ +bugfixes: + - apt - Stop the >= operator from being ignored for packages that are not already installed (https://github.com/ansible/ansible/pull/85254) diff --git a/lib/ansible/modules/apt.py b/lib/ansible/modules/apt.py index 97452f03106..705616bef00 100644 --- a/lib/ansible/modules/apt.py +++ b/lib/ansible/modules/apt.py @@ -516,10 +516,13 @@ def package_best_match(pkgname, version_cmp, version, release, cache): pkgver = policy.get_candidate_ver(pkg) if not pkgver: return None + # Check if the available version matches the requested version if version_cmp == "=" and not fnmatch.fnmatch(pkgver.ver_str, version): # Even though we put in a pin policy, it can be ignored if there is no # possible candidate. return None + if version_cmp == ">=" and not apt_pkg.version_compare(pkgver.ver_str, version) >= 0: + return None return pkgver.ver_str @@ -591,19 +594,17 @@ def package_status(m, pkgname, version_cmp, version, default_release, cache, sta except AttributeError: installed_version = pkg.installedVersion + # Check if the installed version already matches the requested version if version_cmp == "=": - # check if the version is matched as well version_is_installed = fnmatch.fnmatch(installed_version, version) - if version_best and installed_version != version_best and fnmatch.fnmatch(version_best, version): - version_installable = version_best elif version_cmp == ">=": version_is_installed = apt_pkg.version_compare(installed_version, version) >= 0 - if version_best and installed_version != version_best and apt_pkg.version_compare(version_best, version) >= 0: - version_installable = version_best else: version_is_installed = True - if version_best and installed_version != version_best: - version_installable = version_best + + # Check if a better version is available + if version_best and installed_version != version_best: + version_installable = version_best else: version_installable = version_best diff --git a/test/integration/targets/apt/tasks/apt.yml b/test/integration/targets/apt/tasks/apt.yml index d0762344505..8dad838547b 100644 --- a/test/integration/targets/apt/tasks/apt.yml +++ b/test/integration/targets/apt/tasks/apt.yml @@ -221,6 +221,146 @@ - name: uninstall hello with apt apt: pkg=hello state=absent purge=yes +### Get the most recent version string of the hello package +### (It will be used in the subsequent tests) +- name: Search the apt cache for the hello package + shell: apt-cache policy hello | grep Candidate | awk '{print $2}' + register: apt_cache_result + +- name: Store the latest hello package version string + set_fact: + hello_version_current: "{{ apt_cache_result.stdout_lines[0] }}" + +### Install an exact package version with = +- name: Install an exact version of the hello package + apt: + name: "hello={{ hello_version_current }}" + state: present + register: apt_result + +- name: Check hello version install with dpkg + shell: dpkg-query -l hello + failed_when: no + register: dpkg_result + +- name: Verify installation of hello + assert: + that: + - "apt_result.changed" + - "dpkg_result.rc == 0" + +- name: Check hello version + shell: dpkg -s hello | grep Version | awk '{print $2}' + register: hello_version_installed + +- name: Check that the latest version was installed + assert: + that: + - hello_version_installed.stdout_lines[0] == hello_version_current + +- name: Uninstall hello with apt + apt: + name: hello + state: absent + purge: yes + +### Installing an unavailable package version with = must fail +- name: Try to install an unavailable version of the hello package + apt: + name: "hello=10" + state: present + register: apt_result + ignore_errors: true + +- name: Check hello version install with dpkg + shell: dpkg-query -l hello + failed_when: no + register: dpkg_result + +- name: Verify installation of hello + assert: + that: + - apt_result is failed + - "not apt_result.changed" + - "dpkg_result.rc != 0" + +### Install the latest package version with >= +- name: Install the most recent version of a package with the >= operator + apt: + name: "hello>={{ hello_version_current }}" + state: present + register: apt_result + +- name: Check hello version install with dpkg + shell: dpkg-query -l hello + failed_when: no + register: dpkg_result + +- name: Verify installation of hello + assert: + that: + - "apt_result.changed" + - "dpkg_result.rc == 0" + +- name: Check hello version + shell: dpkg -s hello | grep Version | awk '{print $2}' + register: hello_version_installed + +- name: Check that the latest version was installed + assert: + that: + - hello_version_installed.stdout_lines[0] == hello_version_current + +- name: Uninstall hello with apt + apt: + name: hello + state: absent + purge: yes + +### Install a more recent package version with >= +- name: Install some version of a package with the >= operator + apt: + name: "hello>=1" + state: present + register: apt_result + +- name: Check hello version install with dpkg + shell: dpkg-query -l hello + failed_when: no + register: dpkg_result + +- name: Verify installation of hello + assert: + that: + - "apt_result.changed" + - "dpkg_result.rc == 0" + +- name: Uninstall hello with apt + apt: + name: hello + state: absent + purge: yes + +### Installing an unavailable package version with >= must fail +- name: Try to install an unavailable package version with the >= operator + apt: + name: "hello>=10" + state: present + register: apt_result + ignore_errors: true + +- name: Check hello version install with dpkg + shell: dpkg-query -l hello + failed_when: no + register: dpkg_result + +- name: Verify installation of hello + assert: + that: + - apt_result is failed + - "not apt_result.changed" + - "dpkg_result.rc != 0" + # INSTALL WITHOUT REMOVALS - name: Install hello, that conflicts with hello-traditional apt: @@ -235,7 +375,6 @@ - name: verify installation of hello assert: that: - - "apt_result.changed" - "dpkg_result.rc == 0" - name: Try installing hello-traditional, that conflicts with hello @@ -375,6 +514,11 @@ - libslang2-dev # # https://github.com/ansible/ansible/issues/38995 +- name: Make sure that at least one build dependency is missing + apt: + name: build-essential + state: absent + - name: build-dep for a package apt: name: tree