--- # Copyright (c) Ansible Project # GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) # SPDX-License-Identifier: GPL-3.0-or-later ## ## pkgng - prepare test environment ## - name: Remove test package pkgng: name: '{{ pkgng_test_pkg_name }}' state: absent ## ## pkgng - example - state=present for single package ## - name: 'state=present for single package' include_tasks: install_single_package.yml ## ## pkgng - example - state=latest for already up-to-date package ## - name: Upgrade package (idempotent) pkgng: name: '{{ pkgng_test_pkg_name }}' state: latest register: pkgng_example2 - name: Ensure pkgng does not upgrade up-to-date package assert: that: - not pkgng_example2.changed ## ## pkgng - example - state=absent for single package ## - name: Verify package sentinel file is present stat: path: '{{ pkgng_test_pkg_sentinelfile_path }}' get_attributes: false get_checksum: false get_mime: false register: pkgng_example3_stat_before - name: Install package (checkmode) pkgng: name: '{{ pkgng_test_pkg_name }}' check_mode: true register: pkgng_example3_checkmode - name: Remove package pkgng: name: '{{ pkgng_test_pkg_name }}' state: absent register: pkgng_example3 - name: Remove package (idempotent) pkgng: name: '{{ pkgng_test_pkg_name }}' state: absent register: pkgng_example3_idempotent - name: Verify package sentinel file is not present stat: path: '{{ pkgng_test_pkg_sentinelfile_path }}' get_attributes: false get_checksum: false get_mime: false register: pkgng_example3_stat_after - name: Ensure pkgng installs package correctly assert: that: - pkgng_example3_stat_before.stat.exists - pkgng_example3_stat_before.stat.executable - not pkgng_example3_checkmode.changed - pkgng_example3.changed - not pkgng_example3_idempotent.changed - not pkgng_example3_stat_after.stat.exists ## ## pkgng - example - state=latest for out-of-date package ## - name: Install intentionally out-of-date package and upgrade it # # NOTE: The out-of-date package provided is a minimal, # no-contents test package that declares {{ pkgng_test_pkg_name }} with # a version of 0, so it should always be upgraded. # # This test might fail at some point in the # future if the FreeBSD package format receives # breaking changes that prevent pkg from installing # older package formats. # block: - name: Create out-of-date test package import_tasks: create-outofdate-pkg.yml - name: Install out-of-date test package command: 'pkg add {{ pkgng_test_outofdate_pkg_path }}' register: pkgng_example4_prepare - name: Check for any available package upgrades (checkmode) pkgng: name: '*' state: latest check_mode: true register: pkgng_example4_wildcard_checkmode - name: Check for available package upgrade (checkmode) pkgng: name: '{{ pkgng_test_pkg_name }}' state: latest check_mode: true register: pkgng_example4_checkmode - name: Upgrade out-of-date package pkgng: name: '{{ pkgng_test_pkg_name }}' state: latest register: pkgng_example4 - name: Upgrade out-of-date package (idempotent) pkgng: name: '{{ pkgng_test_pkg_name }}' state: latest register: pkgng_example4_idempotent - name: Remove test out-of-date package pkgng: name: '{{ pkgng_test_pkg_name }}' state: absent - name: Ensure pkgng upgrades package correctly assert: that: - not pkgng_example4_prepare.failed - pkgng_example4_wildcard_checkmode.changed - pkgng_example4_checkmode.changed - pkgng_example4.changed - not pkgng_example4_idempotent.changed ## ## pkgng - example - state=latest for out-of-date package without privileges ## - name: Install intentionally out-of-date package and try to upgrade it with unprivileged user block: - ansible.builtin.user: name: powerless shell: /bin/bash - name: Create out-of-date test package import_tasks: create-outofdate-pkg.yml - name: Install out-of-date test package command: 'pkg add {{ pkgng_test_outofdate_pkg_path }}' register: pkgng_example4_nopower_prepare - name: Check for any available package upgrades with unprivileged user become: true become_user: powerless pkgng: name: '*' state: latest register: pkgng_example4_nopower_wildcard ignore_errors: true - name: Remove test out-of-date package pkgng: name: '{{ pkgng_test_pkg_name }}' state: absent - name: Ensure pkgng upgrades package correctly assert: that: - not pkgng_example4_nopower_prepare.failed - pkgng_example4_nopower_wildcard.failed ## ## pkgng - example - Install multiple packages in one command ## - name: Remove test package (checkmode) pkgng: name: '{{ pkgng_test_pkg_name }}' state: absent check_mode: true register: pkgng_example5_prepare - name: Install three packages pkgng: name: - '{{ pkgng_test_pkg_name }}' - fish - busybox register: pkgng_example5 - name: Remove three packages pkgng: name: - '{{ pkgng_test_pkg_name }}' - fish - busybox state: absent register: pkgng_example5_cleanup - name: Ensure pkgng installs multiple packages with one command assert: that: - not pkgng_example5_prepare.changed - pkgng_example5.changed - '(pkgng_example5.stdout | regex_search("^Number of packages to be installed: (\d+)", "\\1", multiline=True) | first | int) >= 3' - '(pkgng_example5.stdout | regex_findall("^Number of packages to be", multiline=True) | count) == 1' - pkgng_example5_cleanup.changed ## ## pkgng - example - state=latest multiple packages, some already installed ## - name: Remove test package (checkmode) pkgng: name: '{{ pkgng_test_pkg_name }}' state: absent check_mode: true register: pkgng_example6_check - name: Create out-of-date test package import_tasks: create-outofdate-pkg.yml - name: Install out-of-date test package command: 'pkg add {{ pkgng_test_outofdate_pkg_path }}' register: pkgng_example6_prepare - name: Upgrade and/or install two packages pkgng: name: - '{{ pkgng_test_pkg_name }}' - fish state: latest register: pkgng_example6 - name: Remove two packages pkgng: name: - '{{ pkgng_test_pkg_name }}' - fish state: absent register: pkgng_example6_cleanup - name: Ensure pkgng installs multiple packages with one command assert: that: - not pkgng_example6_check.changed - not pkgng_example6_prepare.failed - pkgng_example6.changed - '(pkgng_example6.stdout | regex_search("^Number of packages to be installed: (\d+)", "\\1", multiline=True) | first | int) >= 1' - '(pkgng_example6.stdout | regex_search("^Number of packages to be upgraded: (\d+)", "\\1", multiline=True) | first | int) >= 1' # Checking that "will be affected" occurs twice in the output ensures # that the module runs two separate commands for install and upgrade, # as the pkg command only outputs the string once per invocation. - '(pkgng_example6.stdout | regex_findall("will be affected", multiline=True) | count) == 2' - pkgng_example6_cleanup.changed ## ## pkgng - example - autoremove=yes ## - name: "Test autoremove=yes" # # NOTE: FreeBSD 12.0 test runner receives a "connection reset by peer" after ~20% downloaded so we are # only running this on 12.1 or higher # when: ansible_distribution_version is version('12.01', '>=') block: - name: Install GNU autotools pkgng: name: autotools state: latest register: pkgng_example7_prepare_install - name: Remove GNU autotools and run pkg autoremove pkgng: name: autotools state: absent autoremove: true register: pkgng_example7 - name: Check if autoremove uninstalled known autotools dependencies pkgng: name: - autoconf - automake - libtool - m4 state: absent check_mode: true register: pkgng_example7_cleanup - name: Ensure pkgng autoremove works correctly assert: that: - pkgng_example7_prepare_install.changed - "'autoremoved' is in(pkgng_example7.msg)" - not pkgng_example7_cleanup.changed ## ## pkgng - example - single annotations ## - name: Install and annotate single package pkgng: name: '{{ pkgng_test_pkg_name }}' annotation: '+ansibletest_example8=added' register: pkgng_example8_add_annotation - name: Should fail to add duplicate annotation pkgng: name: '{{ pkgng_test_pkg_name }}' annotation: '+ansibletest_example8=duplicate' ignore_errors: true register: pkgng_example8_add_annotation_failure - name: Verify annotation is actually there command: 'pkg annotate -q -S {{ pkgng_test_pkg_name }} ansibletest_example8' register: pkgng_example8_add_annotation_verify - name: Install and annotate single package (checkmode, not changed) pkgng: name: '{{ pkgng_test_pkg_name }}' annotation: '+ansibletest_example8=added' check_mode: true register: pkgng_example8_add_annotation_checkmode_nochange - name: Install and annotate single package (checkmode, changed) pkgng: name: '{{ pkgng_test_pkg_name }}' annotation: '+ansibletest_example8_checkmode=added' check_mode: true register: pkgng_example8_add_annotation_checkmode_change - name: Verify check_mode did not add an annotation command: 'pkg annotate -q -S {{ pkgng_test_pkg_name }} ansibletest_example8_checkmode' register: pkgng_example8_add_annotation_checkmode_change_verify - name: Modify annotation on single package pkgng: name: '{{ pkgng_test_pkg_name }}' annotation: ':ansibletest_example8=modified' register: pkgng_example8_modify_annotation - name: Should fail to modify missing annotation pkgng: name: '{{ pkgng_test_pkg_name }}' annotation: ':ansiblemissing=modified' ignore_errors: true register: pkgng_example8_modify_annotation_failure - name: Verify annotation has been modified command: 'pkg annotate -q -S {{ pkgng_test_pkg_name }} ansibletest_example8' register: pkgng_example8_modify_annotation_verify - name: Remove annotation on single package pkgng: name: '{{ pkgng_test_pkg_name }}' annotation: '-ansibletest_example8' register: pkgng_example8_remove_annotation - name: Verify annotation has been removed command: 'pkg annotate -q -S {{ pkgng_test_pkg_name }} ansibletest_example8' register: pkgng_example8_remove_annotation_verify - name: Ensure pkgng annotations on single packages work correctly assert: that: - pkgng_example8_add_annotation.changed - pkgng_example8_add_annotation_failure.failed - pkgng_example8_add_annotation_checkmode_nochange is not changed - pkgng_example8_add_annotation_checkmode_change is changed - 'pkgng_example8_add_annotation_checkmode_change_verify.stdout_lines | count == 0' - 'pkgng_example8_add_annotation_verify.stdout_lines | first == "added"' - pkgng_example8_modify_annotation.changed - pkgng_example8_modify_annotation_failure.failed - 'pkgng_example8_modify_annotation_verify.stdout_lines | first == "modified"' - pkgng_example8_remove_annotation.changed - 'pkgng_example8_remove_annotation_verify.stdout_lines | count == 0' ## ## pkgng - example - multiple annotations ## - name: Annotate single package with multiple annotations pkgng: name: '{{ pkgng_test_pkg_name }}' annotation: - '+ansibletest_example9_1=added' - '+ansibletest_example9_2=added' register: pkgng_example9_add_annotation - name: Verify annotation is actually there command: 'pkg info -q -A {{ pkgng_test_pkg_name }}' register: pkgng_example9_add_annotation_verify # Assert, below, tests that stdout includes: # ``` # ansibletest_example9_1 : added # ansibletest_example9_2 : added # ``` - name: Multiple annotation operations on single package pkgng: name: '{{ pkgng_test_pkg_name }}' annotation: - ':ansibletest_example9_1=modified' - '+ansibletest_example9_3=added' register: pkgng_example9_multiple_annotation - name: Verify multiple operations succeeded command: 'pkg info -q -A {{ pkgng_test_pkg_name }}' register: pkgng_example9_multiple_annotation_verify # Assert, below, tests that stdout includes: # ``` # ansibletest_example9_1 : modified # ansibletest_example9_2 : added # ansibletest_example9_3 : added # ``` - name: Add multiple annotations with old syntax pkgng: name: '{{ pkgng_test_pkg_name }}' annotation: '+ansibletest_example9_4=added,+ansibletest_example9_5=added' register: pkgng_example9_add_annotation_old - name: Verify annotation is actually there command: 'pkg info -q -A {{ pkgng_test_pkg_name }}' register: pkgng_example9_add_annotation_old_verify # Assert, below, tests that stdout includes: # ``` # ansibletest_example9_4 : added # ansibletest_example9_5 : added # ``` - name: Ensure multiple annotations work correctly assert: that: - pkgng_example9_add_annotation.changed - '(pkgng_example9_add_annotation_verify.stdout_lines | select("match", "ansibletest_example9_[12]\s*:\s*added") | list | count) == 2' - pkgng_example9_multiple_annotation.changed - '(pkgng_example9_multiple_annotation_verify.stdout_lines | select("match", "ansibletest_example9_1\s*:\s*modified") | list | count) == 1' - '(pkgng_example9_multiple_annotation_verify.stdout_lines | select("match", "ansibletest_example9_[23]\s*:\s*added") | list | count) == 2' - pkgng_example9_add_annotation_old.changed - '(pkgng_example9_add_annotation_old_verify.stdout_lines | select("match", "ansibletest_example9_[45]\s*:\s*added") | list | count) == 2' ## ## pkgng - example - invalid annotation strings ## - name: Should fail on invalid annotate strings pkgng: name: '{{ pkgng_test_pkg_name }}' annotation: '{{ item }}' ignore_errors: true register: pkgng_example8_invalid_annotation_failure loop: - 'naked_string' - '/invalid_operation' - ',empty_first_tag=validsecond' - '=notag' - name: Verify invalid annotate strings did not add annotations command: 'pkg info -q -A {{ pkgng_test_pkg_name }}' register: pkgng_example8_invalid_annotation_verify - name: Ensure invalid annotate strings fail safely assert: that: # Invalid strings should not change anything - '(pkgng_example8_invalid_annotation_failure.results | selectattr("changed") | list | count) == 0' # Invalid strings should always fail - '(pkgng_example8_invalid_annotation_failure.results | rejectattr("failed") | list | count) == 0' # Invalid strings should not cause an exception - '(pkgng_example8_invalid_annotation_failure.results | selectattr("exception", "defined") | list | count) == 0' # Verify annotations are unaffected - '(pkgng_example8_invalid_annotation_verify.stdout_lines | select("search", "(naked_string|invalid_operation|empty_first_tag|validsecond|notag)") | list | count) == 0' ## ## pkgng - example - pkgsite=... ## # NOTE: testing for failure here to not have to set up our own # or depend on a third-party, alternate package repo - name: Should fail with invalid pkgsite pkgng: name: '{{ pkgng_test_pkg_name }}' pkgsite: DoesNotExist ignore_errors: true register: pkgng_example10_invalid_pkgsite_failure - name: Ensure invalid pkgsite fails as expected assert: that: - pkgng_example10_invalid_pkgsite_failure.failed - 'pkgng_example10_invalid_pkgsite_failure.stdout is search("^No repositories are enabled.", multiline=True)' ## ## pkgng - example - Install single package in jail ## - name: Test within jail # # NOTE: FreeBSD 12.0 test runner receives a "connection reset by peer" after ~20% downloaded so we are # only running this on 12.1 or higher # # NOTE: FreeBSD 12.3 fails with some kernel mismatch for packages # (someone with FreeBSD knowledge has to take a look) # # NOTE: FreeBSD 12.4 fails to update repositories because it cannot load certificates from /usr/share/keys/pkg/trusted # (someone with FreeBSD knowledge has to take a look) # # NOTE: FreeBSD 13.0 fails to update the package catalogue for unknown reasons (someone with FreeBSD # knowledge has to take a look) # # NOTE: FreeBSD 13.1 fails to update the package catalogue for unknown reasons (someone with FreeBSD # knowledge has to take a look) # # See also # https://github.com/ansible-collections/community.general/issues/5795 when: >- (ansible_distribution_version is version('12.01', '>=') and ansible_distribution_version is version('12.3', '<')) or ansible_distribution_version is version('13.2', '>=') block: - name: Setup testjail include: setup-testjail.yml - name: Install package in jail as rootdir include_tasks: install_single_package.yml vars: pkgng_test_rootdir: /usr/jails/testjail pkgng_test_install_prefix: /usr/jails/testjail pkgng_test_install_cleanup: true - name: Install package in jail include_tasks: install_single_package.yml vars: pkgng_test_jail: testjail pkgng_test_install_prefix: /usr/jails/testjail pkgng_test_install_cleanup: true - name: Install package in jail as chroot include_tasks: install_single_package.yml vars: pkgng_test_chroot: /usr/jails/testjail pkgng_test_install_prefix: /usr/jails/testjail pkgng_test_install_cleanup: true always: - name: Stop and remove testjail failed_when: false changed_when: false command: "ezjail-admin delete -wf testjail"