From 8a754e0858d922e955e71b253c139e071ecec432 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 28 Apr 2024 18:04:21 +0200 Subject: Adding upstream version 2.14.3. Signed-off-by: Daniel Baumann --- test/integration/targets/apt/aliases | 6 + test/integration/targets/apt/defaults/main.yml | 2 + test/integration/targets/apt/handlers/main.yml | 4 + test/integration/targets/apt/meta/main.yml | 3 + .../integration/targets/apt/tasks/apt-builddep.yml | 55 +++ .../targets/apt/tasks/apt-multiarch.yml | 44 ++ test/integration/targets/apt/tasks/apt.yml | 547 +++++++++++++++++++++ test/integration/targets/apt/tasks/downgrade.yml | 77 +++ test/integration/targets/apt/tasks/main.yml | 40 ++ test/integration/targets/apt/tasks/repo.yml | 452 +++++++++++++++++ test/integration/targets/apt/tasks/upgrade.yml | 64 +++ .../targets/apt/tasks/url-with-deps.yml | 56 +++ test/integration/targets/apt/vars/Ubuntu-20.yml | 1 + test/integration/targets/apt/vars/Ubuntu-22.yml | 1 + test/integration/targets/apt/vars/default.yml | 1 + 15 files changed, 1353 insertions(+) create mode 100644 test/integration/targets/apt/aliases create mode 100644 test/integration/targets/apt/defaults/main.yml create mode 100644 test/integration/targets/apt/handlers/main.yml create mode 100644 test/integration/targets/apt/meta/main.yml create mode 100644 test/integration/targets/apt/tasks/apt-builddep.yml create mode 100644 test/integration/targets/apt/tasks/apt-multiarch.yml create mode 100644 test/integration/targets/apt/tasks/apt.yml create mode 100644 test/integration/targets/apt/tasks/downgrade.yml create mode 100644 test/integration/targets/apt/tasks/main.yml create mode 100644 test/integration/targets/apt/tasks/repo.yml create mode 100644 test/integration/targets/apt/tasks/upgrade.yml create mode 100644 test/integration/targets/apt/tasks/url-with-deps.yml create mode 100644 test/integration/targets/apt/vars/Ubuntu-20.yml create mode 100644 test/integration/targets/apt/vars/Ubuntu-22.yml create mode 100644 test/integration/targets/apt/vars/default.yml (limited to 'test/integration/targets/apt') diff --git a/test/integration/targets/apt/aliases b/test/integration/targets/apt/aliases new file mode 100644 index 0000000..5f892f9 --- /dev/null +++ b/test/integration/targets/apt/aliases @@ -0,0 +1,6 @@ +shippable/posix/group2 +destructive +skip/freebsd +skip/osx +skip/macos +skip/rhel diff --git a/test/integration/targets/apt/defaults/main.yml b/test/integration/targets/apt/defaults/main.yml new file mode 100644 index 0000000..7ad2497 --- /dev/null +++ b/test/integration/targets/apt/defaults/main.yml @@ -0,0 +1,2 @@ +apt_foreign_arch: i386 +hello_old_version: 2.6-1 diff --git a/test/integration/targets/apt/handlers/main.yml b/test/integration/targets/apt/handlers/main.yml new file mode 100644 index 0000000..0b6a98f --- /dev/null +++ b/test/integration/targets/apt/handlers/main.yml @@ -0,0 +1,4 @@ +- name: remove package hello + apt: + name: hello + state: absent diff --git a/test/integration/targets/apt/meta/main.yml b/test/integration/targets/apt/meta/main.yml new file mode 100644 index 0000000..162d7fa --- /dev/null +++ b/test/integration/targets/apt/meta/main.yml @@ -0,0 +1,3 @@ +dependencies: + - prepare_tests + - setup_deb_repo diff --git a/test/integration/targets/apt/tasks/apt-builddep.yml b/test/integration/targets/apt/tasks/apt-builddep.yml new file mode 100644 index 0000000..24ee1dc --- /dev/null +++ b/test/integration/targets/apt/tasks/apt-builddep.yml @@ -0,0 +1,55 @@ +# test installing build-deps using netcat and quilt as test victims. +# +# Deps can be discovered like so (taken from ubuntu 12.04) +# ==== +# root@localhost:~ # apt-rdepends --build-depends --follow=DEPENDS netcat +# Reading package lists... Done +# Building dependency tree +# Reading state information... Done +# netcat +# Build-Depends: debhelper (>= 8.0.0) +# Build-Depends: quilt +# root@localhost:~ # +# ==== +# Since many things depend on debhelper, let's just uninstall quilt, then +# install build-dep for netcat to get it back. build-dep doesn't have an +# uninstall, so we don't need to test for reverse actions (eg, uninstall +# build-dep and ensure things are clean) + +# uninstall quilt +- name: check quilt with dpkg + shell: dpkg -s quilt + register: dpkg_result + ignore_errors: true + tags: ['test_apt_builddep'] + +- name: uninstall quilt with apt + apt: pkg=quilt state=absent purge=yes + register: apt_result + when: dpkg_result is successful + tags: ['test_apt_builddep'] + +# install build-dep for rolldice +- name: install rolldice build-dep with apt + apt: pkg=rolldice state=build-dep + register: apt_result + tags: ['test_apt_builddep'] + +- name: verify build_dep of netcat + assert: + that: + - "'changed' in apt_result" + tags: ['test_apt_builddep'] + +# ensure debhelper and qilt are installed +- name: check build_deps with dpkg + shell: dpkg --get-selections | egrep '(debhelper|quilt)' + failed_when: False + register: dpkg_result + tags: ['test_apt_builddep'] + +- name: verify build_deps are really there + assert: + that: + - "dpkg_result.rc == 0" + tags: ['test_apt_builddep'] diff --git a/test/integration/targets/apt/tasks/apt-multiarch.yml b/test/integration/targets/apt/tasks/apt-multiarch.yml new file mode 100644 index 0000000..01f6766 --- /dev/null +++ b/test/integration/targets/apt/tasks/apt-multiarch.yml @@ -0,0 +1,44 @@ +# verify that apt is handling multi-arch systems properly + +- name: load version specific vars + include_vars: '{{ item }}' + with_first_found: + - files: + - '{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.yml' + - 'default.yml' + paths: '../vars' + +- name: add architecture {{ apt_foreign_arch }} + command: dpkg --add-architecture {{ apt_foreign_arch }} + +- name: install {{ multiarch_test_pkg }}:{{ apt_foreign_arch }} with apt + apt: pkg={{ multiarch_test_pkg }}:{{ apt_foreign_arch }} state=present update_cache=yes + register: apt_result + until: apt_result is success + +- name: check {{ multiarch_test_pkg }} version + shell: dpkg -s {{ multiarch_test_pkg }} | grep Version | awk '{print $2}' + register: pkg_version + +- name: uninstall {{ multiarch_test_pkg }}:{{ apt_foreign_arch }} with apt + apt: pkg={{ multiarch_test_pkg }}:{{ apt_foreign_arch }} state=absent purge=yes + +- name: install deb file + apt: deb="/var/cache/apt/archives/{{ multiarch_test_pkg }}_{{ pkg_version.stdout }}_{{ apt_foreign_arch }}.deb" + register: apt_multi_initial + +- name: install deb file again + apt: deb="/var/cache/apt/archives/{{ multiarch_test_pkg }}_{{ pkg_version.stdout }}_{{ apt_foreign_arch }}.deb" + register: apt_multi_secondary + +- name: verify installation of {{ multiarch_test_pkg }}:{{ apt_foreign_arch }} + assert: + that: + - "apt_multi_initial.changed" + - "not apt_multi_secondary.changed" + +- name: remove all {{ apt_foreign_arch }} packages + shell: "apt-get remove -y --allow-remove-essential '*:{{ apt_foreign_arch }}'" + +- name: remove {{ apt_foreign_arch }} architecture + command: dpkg --remove-architecture {{ apt_foreign_arch }} diff --git a/test/integration/targets/apt/tasks/apt.yml b/test/integration/targets/apt/tasks/apt.yml new file mode 100644 index 0000000..d273eda --- /dev/null +++ b/test/integration/targets/apt/tasks/apt.yml @@ -0,0 +1,547 @@ +- name: use Debian mirror + set_fact: + distro_mirror: http://ftp.debian.org/debian + when: ansible_distribution == 'Debian' + +- name: use Ubuntu mirror + set_fact: + distro_mirror: http://archive.ubuntu.com/ubuntu + when: ansible_distribution == 'Ubuntu' + +# UNINSTALL 'python-apt' +# The `apt` module has the smarts to auto-install `python-apt(3)`. To test, we +# will first uninstall `python-apt`. +- name: uninstall python-apt with apt + apt: + pkg: [python-apt, python3-apt] + state: absent + purge: yes + register: apt_result + +# In check mode, auto-install of `python-apt` must fail +- name: test fail uninstall hello without required apt deps in check mode + apt: + pkg: hello + state: absent + purge: yes + register: apt_result + check_mode: yes + ignore_errors: yes + +- name: verify fail uninstall hello without required apt deps in check mode + assert: + that: + - apt_result is failed + - '"If run normally this module can auto-install it." in apt_result.msg' + +- name: check with dpkg + shell: dpkg -s python-apt python3-apt + register: dpkg_result + ignore_errors: true + +# UNINSTALL 'hello' +# With 'python-apt' uninstalled, the first call to 'apt' should install +# python-apt without updating the cache. +- name: uninstall hello with apt and prevent updating the cache + apt: + pkg: hello + state: absent + purge: yes + update_cache: no + register: apt_result + +- name: check hello with dpkg + shell: dpkg-query -l hello + failed_when: False + register: dpkg_result + +- name: verify uninstall hello with apt and prevent updating the cache + assert: + that: + - "'changed' in apt_result" + - apt_result is not changed + - "dpkg_result.rc == 1" + +- name: Test installing fnmatch package + apt: + name: + - hel?o + - he?lo + register: apt_install_fnmatch + +- name: Test uninstalling fnmatch package + apt: + name: + - hel?o + - he?lo + state: absent + register: apt_uninstall_fnmatch + +- name: verify fnmatch + assert: + that: + - apt_install_fnmatch is changed + - apt_uninstall_fnmatch is changed + +- name: Test update_cache 1 (check mode) + apt: + update_cache: true + cache_valid_time: 10 + register: apt_update_cache_1_check_mode + check_mode: true + +- name: Test update_cache 1 + apt: + update_cache: true + cache_valid_time: 10 + register: apt_update_cache_1 + +- name: Test update_cache 2 (check mode) + apt: + update_cache: true + cache_valid_time: 10 + register: apt_update_cache_2_check_mode + check_mode: true + +- name: Test update_cache 2 + apt: + update_cache: true + cache_valid_time: 10 + register: apt_update_cache_2 + +- name: verify update_cache + assert: + that: + - apt_update_cache_1_check_mode is changed + - apt_update_cache_1 is changed + - apt_update_cache_2_check_mode is not changed + - apt_update_cache_2 is not changed + +- name: uninstall apt bindings with apt again + apt: + pkg: [python-apt, python3-apt] + state: absent + purge: yes + +# UNINSTALL 'hello' +# With 'python-apt' uninstalled, the first call to 'apt' should install +# python-apt. +- name: uninstall hello with apt + apt: pkg=hello state=absent purge=yes + register: apt_result + until: apt_result is success + +- name: check hello with dpkg + shell: dpkg-query -l hello + failed_when: False + register: dpkg_result + +- name: verify uninstallation of hello + assert: + that: + - "'changed' in apt_result" + - apt_result is not changed + - "dpkg_result.rc == 1" + +# UNINSTALL AGAIN +- name: uninstall hello with apt + apt: pkg=hello state=absent purge=yes + register: apt_result + +- name: verify no change on re-uninstall + assert: + that: + - "not apt_result.changed" + +# INSTALL +- name: install hello with apt + apt: name=hello state=present + register: apt_result + +- name: check hello with dpkg + shell: dpkg-query -l hello + failed_when: False + register: dpkg_result + +- name: verify installation of hello + assert: + that: + - "apt_result.changed" + - "dpkg_result.rc == 0" + +- name: verify apt module outputs + assert: + that: + - "'changed' in apt_result" + - "'stderr' in apt_result" + - "'stdout' in apt_result" + - "'stdout_lines' in apt_result" + +# INSTALL AGAIN +- name: install hello with apt + apt: name=hello state=present + register: apt_result + +- name: verify no change on re-install + assert: + that: + - "not apt_result.changed" + +# UNINSTALL AGAIN +- name: uninstall hello with apt + apt: pkg=hello state=absent purge=yes + register: apt_result + +# INSTALL WITH VERSION WILDCARD +- name: install hello with apt + apt: name=hello=2.* state=present + register: apt_result + +- name: check hello with wildcard with dpkg + shell: dpkg-query -l hello + failed_when: False + 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 + +- name: check hello architecture + shell: dpkg -s hello | grep Architecture | awk '{print $2}' + register: hello_architecture + +- name: uninstall hello with apt + apt: pkg=hello state=absent purge=yes + +# INSTALL WITHOUT REMOVALS +- name: Install hello, that conflicts with hello-traditional + apt: + pkg: hello + state: present + update_cache: no + +- name: check hello + shell: dpkg-query -l hello + register: dpkg_result + +- name: verify installation of hello + assert: + that: + - "apt_result.changed" + - "dpkg_result.rc == 0" + +- name: Try installing hello-traditional, that conflicts with hello + apt: + pkg: hello-traditional + state: present + fail_on_autoremove: yes + ignore_errors: yes + register: apt_result + +- name: verify failure of installing hello-traditional, because it is required to remove hello to install. + assert: + that: + - apt_result is failed + - '"Packages need to be removed but remove is disabled." in apt_result.msg' + +- name: uninstall hello with apt + apt: + pkg: hello + state: absent + purge: yes + update_cache: no + +- name: install deb file + apt: deb="/var/cache/apt/archives/hello_{{ hello_version.stdout }}_{{ hello_architecture.stdout }}.deb" + register: apt_initial + +- name: install deb file again + apt: deb="/var/cache/apt/archives/hello_{{ hello_version.stdout }}_{{ hello_architecture.stdout }}.deb" + register: apt_secondary + +- name: verify installation of hello + assert: + that: + - "apt_initial.changed" + - "not apt_secondary.changed" + +- name: uninstall hello with apt + apt: pkg=hello state=absent purge=yes + +- name: install deb file from URL + apt: deb="{{ distro_mirror }}/pool/main/h/hello/hello_{{ hello_version.stdout }}_{{ hello_architecture.stdout }}.deb" + register: apt_url + +- name: verify installation of hello + assert: + that: + - "apt_url.changed" + +- name: uninstall hello with apt + apt: pkg=hello state=absent purge=yes + +- name: force install of deb + apt: deb="/var/cache/apt/archives/hello_{{ hello_version.stdout }}_{{ hello_architecture.stdout }}.deb" force=true + register: dpkg_force + +- name: verify installation of hello + assert: + that: + - "dpkg_force.changed" + +# NEGATIVE: upgrade all packages while providing additional packages to install +- name: provide additional packages to install while upgrading all installed packages + apt: pkg=*,test state=latest + ignore_errors: True + register: apt_result + +- name: verify failure of upgrade packages and install + assert: + that: + - "not apt_result.changed" + - "apt_result.failed" + +- name: autoclean during install + apt: pkg=hello state=present autoclean=yes + +- name: undo previous install + apt: pkg=hello state=absent + +# https://github.com/ansible/ansible/issues/23155 +- name: create a repo file + copy: + dest: /etc/apt/sources.list.d/non-existing.list + content: deb http://ppa.launchpad.net/non-existing trusty main + +- name: test for sane error message + apt: + update_cache: yes + register: apt_result + ignore_errors: yes + +- name: verify sane error message + assert: + that: + - "'Failed to fetch' in apt_result['msg']" + - "'403' in apt_result['msg']" + +- name: Clean up + file: + name: /etc/apt/sources.list.d/non-existing.list + state: absent + +# https://github.com/ansible/ansible/issues/28907 +- name: Install parent package + apt: + name: libcaca-dev + +- name: Install child package + apt: + name: libslang2-dev + +- shell: apt-mark showmanual | grep libcaca-dev + ignore_errors: yes + register: parent_output + +- name: Check that parent package is marked as installed manually + assert: + that: + - "'libcaca-dev' in parent_output.stdout" + +- shell: apt-mark showmanual | grep libslang2-dev + ignore_errors: yes + register: child_output + +- name: Check that child package is marked as installed manually + assert: + that: + - "'libslang2-dev' in child_output.stdout" + +- name: Clean up + apt: + name: "{{ pkgs }}" + state: absent + vars: + pkgs: + - libcaca-dev + - libslang2-dev + +# https://github.com/ansible/ansible/issues/38995 +- name: build-dep for a package + apt: + name: tree + state: build-dep + register: apt_result + +- name: Check the result + assert: + that: + - apt_result is changed + +- name: build-dep for a package (idempotency) + apt: + name: tree + state: build-dep + register: apt_result + +- name: Check the result + assert: + that: + - apt_result is not changed + +# check policy_rc_d parameter + +- name: Install unscd but forbid service start + apt: + name: unscd + policy_rc_d: 101 + +- name: Stop unscd service + service: + name: unscd + state: stopped + register: service_unscd_stop + +- name: unscd service shouldn't have been stopped by previous task + assert: + that: service_unscd_stop is not changed + +- name: Uninstall unscd + apt: + name: unscd + policy_rc_d: 101 + +- name: Create incorrect /usr/sbin/policy-rc.d + copy: + dest: /usr/sbin/policy-rc.d + content: apt integration test + mode: 0755 + +- name: Install unscd but forbid service start + apt: + name: unscd + policy_rc_d: 101 + +- name: Stop unscd service + service: + name: unscd + state: stopped + register: service_unscd_stop + +- name: unscd service shouldn't have been stopped by previous task + assert: + that: service_unscd_stop is not changed + +- name: Create incorrect /usr/sbin/policy-rc.d + copy: + dest: /usr/sbin/policy-rc.d + content: apt integration test + mode: 0755 + register: policy_rc_d + +- name: Check if /usr/sbin/policy-rc.d was correctly backed-up during unscd install + assert: + that: policy_rc_d is not changed + +- name: Delete /usr/sbin/policy-rc.d + file: + path: /usr/sbin/policy-rc.d + state: absent + +# https://github.com/ansible/ansible/issues/65325 +- name: Download and install old version of hello (to test allow_change_held_packages option) + apt: "deb=https://ci-files.testing.ansible.com/test/integration/targets/dpkg_selections/hello_{{ hello_old_version }}_amd64.deb" + notify: + - remove package hello + +- name: Put hello on hold + shell: apt-mark hold hello + +- name: Get hold list + shell: apt-mark showhold + register: allow_change_held_packages_hold + +- name: Check that the package hello is on the hold list + assert: + that: + - "'hello' in allow_change_held_packages_hold.stdout" + +- name: Try updating package to the latest version (allow_change_held_packages=no) + apt: + name: hello + state: latest + ignore_errors: True + register: allow_change_held_packages_failed_update + +- name: Get the version of the package + shell: dpkg -s hello | grep Version | awk '{print $2}' + register: allow_change_held_packages_hello_version + +- name: Verify that the package was not updated (apt returns with an error) + assert: + that: + - "allow_change_held_packages_failed_update is failed" + - "'--allow-change-held-packages' in allow_change_held_packages_failed_update.stderr" + - "allow_change_held_packages_hello_version.stdout == hello_old_version" + +- name: Try updating package to the latest version (allow_change_held_packages=yes) + apt: + name: hello + state: latest + allow_change_held_packages: yes + register: allow_change_held_packages_successful_update + +- name: Get the version of the package + shell: dpkg -s hello | grep Version | awk '{print $2}' + register: allow_change_held_packages_hello_version + +- name: Verify that the package was updated + assert: + that: + - "allow_change_held_packages_successful_update is changed" + - "allow_change_held_packages_hello_version.stdout != hello_old_version" + +- name: Try updating package to the latest version again + apt: + name: hello + state: latest + allow_change_held_packages: yes + register: allow_change_held_packages_no_update + +- name: Get the version of the package + shell: dpkg -s hello | grep Version | awk '{print $2}' + register: allow_change_held_packages_hello_version_again + +- name: Verify that the package was not updated + assert: + that: + - "allow_change_held_packages_no_update is not changed" + - "allow_change_held_packages_hello_version.stdout == allow_change_held_packages_hello_version_again.stdout" + +# Virtual package +- name: Install a virtual package + apt: + package: + - emacs-nox + - yaml-mode # <- the virtual package + state: latest + register: install_virtual_package_result + +- name: Check the virtual package install result + assert: + that: + - install_virtual_package_result is changed + +- name: Clean up virtual-package install + apt: + package: + - emacs-nox + - elpa-yaml-mode + state: absent + purge: yes diff --git a/test/integration/targets/apt/tasks/downgrade.yml b/test/integration/targets/apt/tasks/downgrade.yml new file mode 100644 index 0000000..896b644 --- /dev/null +++ b/test/integration/targets/apt/tasks/downgrade.yml @@ -0,0 +1,77 @@ +- block: + - name: Disable ubuntu repos so system packages are not upgraded and do not change testing env + command: mv /etc/apt/sources.list /etc/apt/sources.list.backup + + - name: install latest foo + apt: + name: foo + state: latest + allow_unauthenticated: yes + + - name: check foo version + shell: dpkg -s foo | grep Version | awk '{print $2}' + register: apt_downgrade_foo_version + + - name: ensure the correct version of foo has been installed + assert: + that: + - "'1.0.1' in apt_downgrade_foo_version.stdout" + + - name: try to downgrade foo + apt: + name: foo=1.0.0 + state: present + allow_unauthenticated: yes + ignore_errors: yes + register: apt_downgrade_foo_fail + + - name: verify failure of downgrading without allow downgrade flag + assert: + that: + - apt_downgrade_foo_fail is failed + + - name: try to downgrade foo with flag + apt: + name: foo=1.0.0 + state: present + allow_downgrade: yes + allow_unauthenticated: yes + register: apt_downgrade_foo_succeed + + - name: verify success of downgrading with allow downgrade flag + assert: + that: + - apt_downgrade_foo_succeed is success + + - name: check foo version + shell: dpkg -s foo | grep Version | awk '{print $2}' + register: apt_downgrade_foo_version + + - name: check that version downgraded correctly + assert: + that: + - "'1.0.0' in apt_downgrade_foo_version.stdout" + - "{{ apt_downgrade_foo_version.changed }}" + + - name: downgrade foo with flag again + apt: + name: foo=1.0.0 + state: present + allow_downgrade: yes + allow_unauthenticated: yes + register: apt_downgrade_second_downgrade + + - name: check that nothing has changed (idempotent) + assert: + that: + - "apt_downgrade_second_downgrade.changed == false" + + always: + - name: Clean up + apt: + pkg: foo,foobar + state: absent + autoclean: yes + + - name: Restore ubuntu repos + command: mv /etc/apt/sources.list.backup /etc/apt/sources.list diff --git a/test/integration/targets/apt/tasks/main.yml b/test/integration/targets/apt/tasks/main.yml new file mode 100644 index 0000000..13d3e4f --- /dev/null +++ b/test/integration/targets/apt/tasks/main.yml @@ -0,0 +1,40 @@ +# (c) 2014, James Tanner + +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +- block: + - import_tasks: 'apt.yml' + + - import_tasks: 'url-with-deps.yml' + + - import_tasks: 'apt-multiarch.yml' + when: + - ansible_userspace_architecture != apt_foreign_arch + + - import_tasks: 'apt-builddep.yml' + + - block: + - import_tasks: 'repo.yml' + always: + - file: + path: /etc/apt/sources.list.d/file_tmp_repo.list + state: absent + - file: + name: "{{ repodir }}" + state: absent + + when: + - ansible_distribution in ('Ubuntu', 'Debian') diff --git a/test/integration/targets/apt/tasks/repo.yml b/test/integration/targets/apt/tasks/repo.yml new file mode 100644 index 0000000..d4cce78 --- /dev/null +++ b/test/integration/targets/apt/tasks/repo.yml @@ -0,0 +1,452 @@ +- block: + - name: Install foo package version 1.0.0 + apt: + name: foo=1.0.0 + allow_unauthenticated: yes + register: apt_result + + - name: Check install with dpkg + shell: dpkg-query -l foo + register: dpkg_result + + - name: Check if install was successful + assert: + that: + - "apt_result is success" + - "dpkg_result is success" + - "'1.0.0' in dpkg_result.stdout" + + - name: Update to foo version 1.0.1 + apt: + name: foo + state: latest + allow_unauthenticated: yes + register: apt_result + + - name: Check install with dpkg + shell: dpkg-query -l foo + register: dpkg_result + + - name: Check if install was successful + assert: + that: + - "apt_result is success" + - "dpkg_result is success" + - "'1.0.1' in dpkg_result.stdout" + always: + - name: Clean up + apt: + name: foo + state: absent + allow_unauthenticated: yes + +- name: Try to install non-existent version + apt: + name: foo=99 + state: present + ignore_errors: true + register: apt_result + +- name: Check if install failed + assert: + that: + - apt_result is failed + +# https://github.com/ansible/ansible/issues/30638 +- block: + - name: Don't install foo=1.0.1 since foo is not installed and only_upgrade is set + apt: + name: foo=1.0.1 + state: present + only_upgrade: yes + allow_unauthenticated: yes + ignore_errors: yes + register: apt_result + + - name: Check that foo was not upgraded + assert: + that: + - "apt_result is not changed" + - "apt_result is success" + + - apt: + name: foo=1.0.0 + allow_unauthenticated: yes + + - name: Upgrade foo to 1.0.1 but don't upgrade foobar since it is not installed + apt: + name: foobar=1.0.1,foo=1.0.1 + state: present + only_upgrade: yes + allow_unauthenticated: yes + register: apt_result + + - name: Check install with dpkg + shell: "dpkg-query -l {{ item }}" + register: dpkg_result + ignore_errors: yes + loop: + - foobar + - foo + + - name: Check if install was successful + assert: + that: + - "apt_result is success" + - "dpkg_result.results[0] is failure" + - "'1.0.1' not in dpkg_result.results[0].stdout" + - "dpkg_result.results[1] is success" + - "'1.0.1' in dpkg_result.results[1].stdout" + always: + - name: Clean up + apt: + name: foo + state: absent + allow_unauthenticated: yes + +- block: + - name: Install foo=1.0.0 + apt: + name: foo=1.0.0 + + - name: Run version test matrix + apt: + name: foo{{ item.0 }} + default_release: '{{ item.1 }}' + state: '{{ item.2 | ternary("latest","present") }}' + check_mode: true + register: apt_result + loop: + # [filter, release, state_latest, expected] + - ["", null, false, null] + - ["", null, true, "1.0.1"] + - ["=1.0.0", null, false, null] + - ["=1.0.0", null, true, null] + - ["=1.0.1", null, false, "1.0.1"] + #- ["=1.0.*", null, false, null] # legacy behavior. should not upgrade without state=latest + - ["=1.0.*", null, true, "1.0.1"] + - [">=1.0.0", null, false, null] + - [">=1.0.0", null, true, "1.0.1"] + - [">=1.0.1", null, false, "1.0.1"] + - ["", "testing", false, null] + - ["", "testing", true, "2.0.1"] + - ["=2.0.0", null, false, "2.0.0"] + - [">=2.0.0", "testing", false, "2.0.1"] + + - name: Validate version test matrix + assert: + that: + - (item.item.3 is not none) == (item.stdout is defined) + - item.item.3 is none or "Inst foo [1.0.0] (" + item.item.3 + " localhost [all])" in item.stdout_lines + loop: '{{ apt_result.results }}' + + - name: Pin foo=1.0.0 + copy: + content: |- + Package: foo + Pin: version 1.0.0 + Pin-Priority: 1000 + dest: /etc/apt/preferences.d/foo + + - name: Run pinning version test matrix + apt: + name: foo{{ item.0 }} + default_release: '{{ item.1 }}' + state: '{{ item.2 | ternary("latest","present") }}' + check_mode: true + ignore_errors: true + register: apt_result + loop: + # [filter, release, state_latest, expected] # expected=null for no change. expected=False to assert an error + - ["", null, false, null] + - ["", null, true, null] + - ["=1.0.0", null, false, null] + - ["=1.0.0", null, true, null] + - ["=1.0.1", null, false, "1.0.1"] + #- ["=1.0.*", null, false, null] # legacy behavior. should not upgrade without state=latest + - ["=1.0.*", null, true, "1.0.1"] + - [">=1.0.0", null, false, null] + - [">=1.0.0", null, true, null] + - [">=1.0.1", null, false, False] + - ["", "testing", false, null] + - ["", "testing", true, null] + - ["=2.0.0", null, false, "2.0.0"] + - [">=2.0.0", "testing", false, False] + + - name: Validate pinning version test matrix + assert: + that: + - (item.item.3 != False) or (item.item.3 == False and item is failed) + - (item.item.3 is string) == (item.stdout is defined) + - item.item.3 is not string or "Inst foo [1.0.0] (" + item.item.3 + " localhost [all])" in item.stdout_lines + loop: '{{ apt_result.results }}' + + always: + - name: Uninstall foo + apt: + name: foo + state: absent + + - name: Unpin foo + file: + path: /etc/apt/preferences.d/foo + state: absent + +# https://github.com/ansible/ansible/issues/35900 +- block: + - name: Disable ubuntu repos so system packages are not upgraded and do not change testing env + command: mv /etc/apt/sources.list /etc/apt/sources.list.backup + + - name: Install foobar, installs foo as a dependency + apt: + name: foobar=1.0.0 + allow_unauthenticated: yes + + - name: mark foobar as auto for next test + shell: apt-mark auto foobar + + - name: Install foobar (marked as manual) (check mode) + apt: + name: foobar=1.0.1 + allow_unauthenticated: yes + check_mode: yes + register: manual_foobar_install_check_mode + + - name: check foobar was not marked as manually installed by check mode + shell: apt-mark showmanual | grep foobar + ignore_errors: yes + register: showmanual + + - assert: + that: + - manual_foobar_install_check_mode.changed + - "'foobar' not in showmanual.stdout" + + - name: Install foobar (marked as manual) + apt: + name: foobar=1.0.1 + allow_unauthenticated: yes + register: manual_foobar_install + + - name: check foobar was marked as manually installed + shell: apt-mark showmanual | grep foobar + ignore_errors: yes + register: showmanual + + - assert: + that: + - manual_foobar_install.changed + - "'foobar' in showmanual.stdout" + + - name: Upgrade foobar to a version which does not depend on foo, autoremove should remove foo + apt: + upgrade: dist + autoremove: yes + allow_unauthenticated: yes + + - 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" + + always: + - name: Clean up + apt: + pkg: foo,foobar + state: absent + autoclean: yes + + - name: Restore ubuntu repos + command: mv /etc/apt/sources.list.backup /etc/apt/sources.list + + +# https://github.com/ansible/ansible/issues/26298 +- block: + - name: Disable ubuntu repos so system packages are not upgraded and do not change testing env + command: mv /etc/apt/sources.list /etc/apt/sources.list.backup + + - 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: + pkg: foo,foobar + state: absent + autoclean: yes + + - name: Restore ubuntu repos + command: mv /etc/apt/sources.list.backup /etc/apt/sources.list + +- name: Downgrades + import_tasks: "downgrade.yml" + +- name: Upgrades + block: + - import_tasks: "upgrade.yml" + vars: + aptitude_present: "{{ True | bool }}" + upgrade_type: "dist" + force_apt_get: "{{ False | bool }}" + + - name: Check if aptitude is installed + command: dpkg-query --show --showformat='${db:Status-Abbrev}' aptitude + register: aptitude_status + + - name: Remove aptitude, if installed, to test fall-back to apt-get + apt: + pkg: aptitude + state: absent + when: + - aptitude_status.stdout.find('ii') != -1 + + - include_tasks: "upgrade.yml" + vars: + aptitude_present: "{{ False | bool }}" + upgrade_type: "{{ item.upgrade_type }}" + force_apt_get: "{{ item.force_apt_get }}" + with_items: + - { upgrade_type: safe, force_apt_get: False } + - { upgrade_type: full, force_apt_get: False } + - { upgrade_type: safe, force_apt_get: True } + - { upgrade_type: full, force_apt_get: True } + + - name: (Re-)Install aptitude, run same tests again + apt: + pkg: aptitude + state: present + + - include_tasks: "upgrade.yml" + vars: + aptitude_present: "{{ True | bool }}" + upgrade_type: "{{ item.upgrade_type }}" + force_apt_get: "{{ item.force_apt_get }}" + with_items: + - { upgrade_type: safe, force_apt_get: False } + - { upgrade_type: full, force_apt_get: False } + - { upgrade_type: safe, force_apt_get: True } + - { upgrade_type: full, force_apt_get: True } + + - name: Remove aptitude if not originally present + apt: + pkg: aptitude + state: absent + when: + - aptitude_status.stdout.find('ii') == -1 + +- block: + - name: Install the foo package with diff=yes + apt: + name: foo + allow_unauthenticated: yes + diff: yes + register: apt_result + + - name: Check the content of diff.prepared + assert: + that: + - apt_result is success + - "'The following NEW packages will be installed:\n foo' in apt_result.diff.prepared" + always: + - name: Clean up + apt: + name: foo + state: absent + allow_unauthenticated: yes + +- block: + - name: Install foo package version 1.0.0 with force=yes, implies allow_unauthenticated=yes + apt: + name: foo=1.0.0 + force: yes + register: apt_result + + - name: Check install with dpkg + shell: dpkg-query -l foo + register: dpkg_result + + - name: Check if install was successful + assert: + that: + - "apt_result is success" + - "dpkg_result is success" + - "'1.0.0' in dpkg_result.stdout" + always: + - name: Clean up + apt: + name: foo + state: absent + allow_unauthenticated: yes diff --git a/test/integration/targets/apt/tasks/upgrade.yml b/test/integration/targets/apt/tasks/upgrade.yml new file mode 100644 index 0000000..cf747c8 --- /dev/null +++ b/test/integration/targets/apt/tasks/upgrade.yml @@ -0,0 +1,64 @@ +- block: + - name: Disable ubuntu repos so system packages are not upgraded and do not change testing env + command: mv /etc/apt/sources.list /etc/apt/sources.list.backup + + - name: install foo-1.0.0 + apt: + name: foo=1.0.0 + state: present + allow_unauthenticated: yes + + - name: check foo version + shell: dpkg -s foo | grep Version | awk '{print $2}' + register: foo_version + + - name: ensure the correct version of foo has been installed + assert: + that: + - "'1.0.0' in foo_version.stdout" + + - name: "(upgrade type: {{upgrade_type}}) upgrade packages to latest version, force_apt_get: {{force_apt_get}}" + apt: + upgrade: "{{ upgrade_type }}" + force_apt_get: "{{ force_apt_get }}" + force: yes + register: upgrade_result + + - name: check foo version + shell: dpkg -s foo | grep Version | awk '{print $2}' + register: foo_version + + - name: check that warning is not given when force_apt_get set + assert: + that: + - "'warnings' not in upgrade_result" + when: + - force_apt_get + + - name: check that old version upgraded correctly + assert: + that: + - "'1.0.0' not in foo_version.stdout" + - "{{ foo_version.changed }}" + + - name: "(upgrade type: {{upgrade_type}}) upgrade packages to latest version (Idempotant)" + apt: + upgrade: "{{ upgrade_type }}" + force_apt_get: "{{ force_apt_get }}" + force: yes + register: second_upgrade_result + + - name: check that nothing has changed (Idempotant) + assert: + that: + - "second_upgrade_result.changed == false" + + always: + - name: Clean up + apt: + pkg: foo,foobar + state: absent + autoclean: yes + + - name: Restore ubuntu repos + command: mv /etc/apt/sources.list.backup /etc/apt/sources.list diff --git a/test/integration/targets/apt/tasks/url-with-deps.yml b/test/integration/targets/apt/tasks/url-with-deps.yml new file mode 100644 index 0000000..7c70eb9 --- /dev/null +++ b/test/integration/targets/apt/tasks/url-with-deps.yml @@ -0,0 +1,56 @@ +- block: + - name: Install https transport for apt + apt: + name: apt-transport-https + + - name: Ensure echo-hello is not installed + apt: + name: echo-hello + state: absent + purge: yes + + # Note that this .deb is just a stupidly tiny one that has a dependency + # on vim-tiny. Really any .deb will work here so long as it has + # dependencies that exist in a repo and get brought in. + # The source and files for building this .deb can be found here: + # https://ci-files.testing.ansible.com/test/integration/targets/apt/echo-hello-source.tar.gz + - name: Install deb file with dependencies from URL (check_mode) + apt: + deb: https://ci-files.testing.ansible.com/test/integration/targets/apt/echo-hello_1.0_all.deb + check_mode: true + register: apt_url_deps_check_mode + + - name: check to make sure we didn't install the package due to check_mode + shell: dpkg-query -l echo-hello + failed_when: false + register: dpkg_result_check_mode + + - name: verify check_mode installation of echo-hello + assert: + that: + - apt_url_deps_check_mode is changed + - dpkg_result_check_mode.rc != 0 + + - name: Install deb file with dependencies from URL (for real this time) + apt: + deb: https://ci-files.testing.ansible.com/test/integration/targets/apt/echo-hello_1.0_all.deb + register: apt_url_deps + + - name: check to make sure we installed the package + shell: dpkg-query -l echo-hello + failed_when: False + register: dpkg_result + + - name: verify real installation of echo-hello + assert: + that: + - apt_url_deps is changed + - dpkg_result is successful + - dpkg_result.rc == 0 + + always: + - name: uninstall echo-hello with apt + apt: + pkg: echo-hello + state: absent + purge: yes diff --git a/test/integration/targets/apt/vars/Ubuntu-20.yml b/test/integration/targets/apt/vars/Ubuntu-20.yml new file mode 100644 index 0000000..7b32755 --- /dev/null +++ b/test/integration/targets/apt/vars/Ubuntu-20.yml @@ -0,0 +1 @@ +multiarch_test_pkg: libunistring2 diff --git a/test/integration/targets/apt/vars/Ubuntu-22.yml b/test/integration/targets/apt/vars/Ubuntu-22.yml new file mode 100644 index 0000000..7b32755 --- /dev/null +++ b/test/integration/targets/apt/vars/Ubuntu-22.yml @@ -0,0 +1 @@ +multiarch_test_pkg: libunistring2 diff --git a/test/integration/targets/apt/vars/default.yml b/test/integration/targets/apt/vars/default.yml new file mode 100644 index 0000000..bed3a96 --- /dev/null +++ b/test/integration/targets/apt/vars/default.yml @@ -0,0 +1 @@ +multiarch_test_pkg: hello -- cgit v1.2.3