Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package ansible-core for openSUSE:Factory checked in at 2025-07-16 17:36:03 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/ansible-core (Old) and /work/SRC/openSUSE:Factory/.ansible-core.new.7373 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ansible-core" Wed Jul 16 17:36:03 2025 rev:45 rq:1293661 version:2.18.7 Changes: -------- --- /work/SRC/openSUSE:Factory/ansible-core/ansible-core.changes 2025-05-27 18:44:41.926884780 +0200 +++ /work/SRC/openSUSE:Factory/.ansible-core.new.7373/ansible-core.changes 2025-07-16 17:36:20.222920616 +0200 @@ -1,0 +2,22 @@ +Wed Jul 16 06:42:28 UTC 2025 - Johannes Kastl <opensuse_buildserv...@ojkastl.de> + +- update to 2.18.7: + * Minor Changes + - ansible-test - Add RHEL 10.0 as a remote platform for + testing. + * Bugfixes + - ansible-doc will no longer ignore docs for modules without an + extension (#85279). + - ansible-pull change detection will now work independently of + callback or result format settings. + - ansible-test - Fix Python relative import resolution from + __init__.py files when using change detection. + - dnf5 - handle all libdnf5 specific exceptions (#84634) + - meta - avoid traceback when retrieving the meta task name + (#85367). + - password lookup - fix acquiring the lock when human-readable + FileExistsError error message is not English. + - user - Set timeout for passphrase interaction. + - user - Update prompt for SSH key passphrase (#84484). + +------------------------------------------------------------------- Old: ---- ansible_core-2.18.6.tar.gz ansible_core-2.18.6.tar.gz.sha256 New: ---- ansible_core-2.18.7.tar.gz ansible_core-2.18.7.tar.gz.sha256 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ ansible-core.spec ++++++ --- /var/tmp/diff_new_pack.efTbWc/_old 2025-07-16 17:36:23.003036861 +0200 +++ /var/tmp/diff_new_pack.efTbWc/_new 2025-07-16 17:36:23.011037196 +0200 @@ -43,7 +43,7 @@ %endif Name: ansible-core -Version: 2.18.6 +Version: 2.18.7 Release: 0 Summary: Radically simple IT automation License: GPL-3.0-or-later ++++++ ansible_core-2.18.6.tar.gz -> ansible_core-2.18.7.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/PKG-INFO new/ansible_core-2.18.7/PKG-INFO --- old/ansible_core-2.18.6/PKG-INFO 2025-05-19 18:56:48.000000000 +0200 +++ new/ansible_core-2.18.7/PKG-INFO 2025-07-15 19:46:32.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.4 Name: ansible-core -Version: 2.18.6 +Version: 2.18.7 Summary: Radically simple IT automation Author: Ansible Project Project-URL: Homepage, https://ansible.com/ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/ansible_core.egg-info/PKG-INFO new/ansible_core-2.18.7/ansible_core.egg-info/PKG-INFO --- old/ansible_core-2.18.6/ansible_core.egg-info/PKG-INFO 2025-05-19 18:56:48.000000000 +0200 +++ new/ansible_core-2.18.7/ansible_core.egg-info/PKG-INFO 2025-07-15 19:46:32.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.4 Name: ansible-core -Version: 2.18.6 +Version: 2.18.7 Summary: Radically simple IT automation Author: Ansible Project Project-URL: Homepage, https://ansible.com/ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/ansible_core.egg-info/SOURCES.txt new/ansible_core-2.18.7/ansible_core.egg-info/SOURCES.txt --- old/ansible_core-2.18.6/ansible_core.egg-info/SOURCES.txt 2025-05-19 18:56:48.000000000 +0200 +++ new/ansible_core-2.18.7/ansible_core.egg-info/SOURCES.txt 2025-07-15 19:46:32.000000000 +0200 @@ -795,7 +795,11 @@ test/integration/targets/ansible-doc/filter_plugins/donothing.yml test/integration/targets/ansible-doc/filter_plugins/other.py test/integration/targets/ansible-doc/filter_plugins/split.yml +test/integration/targets/ansible-doc/library/bogus_facts +test/integration/targets/ansible-doc/library/bogus_facts.py test/integration/targets/ansible-doc/library/double_doc.py +test/integration/targets/ansible-doc/library/facts_one +test/integration/targets/ansible-doc/library/facts_one.yml test/integration/targets/ansible-doc/library/test_docs.py test/integration/targets/ansible-doc/library/test_docs_missing_description.py test/integration/targets/ansible-doc/library/test_docs_no_metadata.py @@ -3356,10 +3360,10 @@ test/integration/targets/roles_var_inheritance/roles/nested_dep/meta/main.yml test/integration/targets/roles_var_inheritance/roles/nested_dep/tasks/main.yml test/integration/targets/rpm_key/aliases -test/integration/targets/rpm_key/defaults/main.yaml test/integration/targets/rpm_key/meta/main.yml test/integration/targets/rpm_key/tasks/main.yaml test/integration/targets/rpm_key/tasks/rpm_key.yaml +test/integration/targets/rpm_key/vars/main.yml test/integration/targets/run_modules/aliases test/integration/targets/run_modules/args.json test/integration/targets/run_modules/run_raw_args.yml @@ -3445,6 +3449,7 @@ test/integration/targets/setup_paramiko/install-Alpine-3-python-3.yml test/integration/targets/setup_paramiko/install-Darwin-python-3.yml test/integration/targets/setup_paramiko/install-FreeBSD-python-3.yml +test/integration/targets/setup_paramiko/install-RedHat-10-python-3.yml test/integration/targets/setup_paramiko/install-RedHat-8-python-3.yml test/integration/targets/setup_paramiko/install-RedHat-9-python-3.yml test/integration/targets/setup_paramiko/install-fail.yml @@ -3456,6 +3461,7 @@ test/integration/targets/setup_paramiko/uninstall-Alpine-3-python-3.yml test/integration/targets/setup_paramiko/uninstall-Darwin-python-3.yml test/integration/targets/setup_paramiko/uninstall-FreeBSD-python-3.yml +test/integration/targets/setup_paramiko/uninstall-RedHat-10-python-3.yml test/integration/targets/setup_paramiko/uninstall-RedHat-8-python-3.yml test/integration/targets/setup_paramiko/uninstall-RedHat-9-python-3.yml test/integration/targets/setup_paramiko/uninstall-apt-python-3.yml diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/changelogs/CHANGELOG-v2.18.rst new/ansible_core-2.18.7/changelogs/CHANGELOG-v2.18.rst --- old/ansible_core-2.18.6/changelogs/CHANGELOG-v2.18.rst 2025-05-19 18:56:48.000000000 +0200 +++ new/ansible_core-2.18.7/changelogs/CHANGELOG-v2.18.rst 2025-07-15 19:46:32.000000000 +0200 @@ -4,6 +4,32 @@ .. contents:: Topics +v2.18.7 +======= + +Release Summary +--------------- + +| Release Date: 2025-07-15 +| `Porting Guide <https://docs.ansible.com/ansible-core/2.18/porting_guides/porting_guide_core_2.18.html>`__ + +Minor Changes +------------- + +- ansible-test - Add RHEL 10.0 as a remote platform for testing. + +Bugfixes +-------- + +- ansible-doc will no longer ignore docs for modules without an extension (https://github.com/ansible/ansible/issues/85279). +- ansible-pull change detection will now work independently of callback or result format settings. +- ansible-test - Fix Python relative import resolution from ``__init__.py`` files when using change detection. +- dnf5 - handle all libdnf5 specific exceptions (https://github.com/ansible/ansible/issues/84634) +- meta - avoid traceback when retrieving the meta task name (https://github.com/ansible/ansible/issues/85367). +- password lookup - fix acquiring the lock when human-readable FileExistsError error message is not English. +- user - Set timeout for passphrase interaction. +- user - Update prompt for SSH key passphrase (https://github.com/ansible/ansible/issues/84484). + v2.18.6 ======= diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/changelogs/changelog.yaml new/ansible_core-2.18.7/changelogs/changelog.yaml --- old/ansible_core-2.18.6/changelogs/changelog.yaml 2025-05-19 18:56:48.000000000 +0200 +++ new/ansible_core-2.18.7/changelogs/changelog.yaml 2025-07-15 19:46:32.000000000 +0200 @@ -865,3 +865,47 @@ - ensure_remote_perms.yml - win-script-become.yml release_date: '2025-05-12' + 2.18.7: + changes: + release_summary: '| Release Date: 2025-07-15 + + | `Porting Guide <https://docs.ansible.com/ansible-core/2.18/porting_guides/porting_guide_core_2.18.html>`__ + + ' + codename: Fool in the Rain + fragments: + - 2.18.7_summary.yaml + release_date: '2025-07-15' + 2.18.7rc1: + changes: + bugfixes: + - ansible-doc will no longer ignore docs for modules without an extension (https://github.com/ansible/ansible/issues/85279). + - ansible-pull change detection will now work independently of callback or result + format settings. + - ansible-test - Fix Python relative import resolution from ``__init__.py`` + files when using change detection. + - dnf5 - handle all libdnf5 specific exceptions (https://github.com/ansible/ansible/issues/84634) + - meta - avoid traceback when retrieving the meta task name (https://github.com/ansible/ansible/issues/85367). + - password lookup - fix acquiring the lock when human-readable FileExistsError + error message is not English. + - user - Set timeout for passphrase interaction. + - user - Update prompt for SSH key passphrase (https://github.com/ansible/ansible/issues/84484). + minor_changes: + - ansible-test - Add RHEL 10.0 as a remote platform for testing. + release_summary: '| Release Date: 2025-07-08 + + | `Porting Guide <https://docs.ansible.com/ansible-core/2.18/porting_guides/porting_guide_core_2.18.html>`__ + + ' + codename: Fool in the Rain + fragments: + - 2.18.7rc1_summary.yaml + - 84634-dnf5-all-exceptions.yml + - adoc_noext_fix.yml + - ansible-test-change-detection-fix.yml + - ansible-test-rhel-10.yml + - fix-lookup-password-lock-acquisition.yml + - meta_raw_params.yml + - pull_changed_fix.yml + - user_passphrase.yml + release_date: '2025-07-08' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/lib/ansible/cli/pull.py new/ansible_core-2.18.7/lib/ansible/cli/pull.py --- old/ansible_core-2.18.6/lib/ansible/cli/pull.py 2025-05-19 18:56:48.000000000 +0200 +++ new/ansible_core-2.18.7/lib/ansible/cli/pull.py 2025-07-15 19:46:32.000000000 +0200 @@ -31,6 +31,34 @@ display = Display() +SAFE_OUTPUT_ENV = { + 'ANSIBLE_CALLBACK_RESULT_FORMAT': 'json', + 'ANSIBLE_LOAD_CALLBACK_PLUGINS': '0', +} + + +def safe_output_env(f): + + def wrapper(*args, **kwargs): + + orig = {} + + for k, v in SAFE_OUTPUT_ENV.items(): + orig[k] = os.environ.get(k, None) + os.environ[k] = v + + result = f(*args, **kwargs) + + for key in orig.keys(): + if orig[key] is None: + del os.environ[key] + else: + os.environ[key] = orig[key] + + return result + + return wrapper + class PullCLI(CLI): ''' Used to pull a remote copy of ansible on each managed node, @@ -42,7 +70,7 @@ you should use an external scheduler and/or locking to ensure there are no clashing operations. The setup playbook can be tuned to change the cron frequency, logging locations, and parameters to ansible-pull. - This is useful both for extreme scale-out as well as periodic remediation. + This is useful both for extreme scale-out and periodic remediation. Usage of the 'fetch' module to retrieve logs from ansible-pull runs would be an excellent way to gather and analyze remote logs from ansible-pull. ''' @@ -76,8 +104,9 @@ return inv_opts def init_parser(self): - ''' create an options parser for bin/ansible ''' + """ Specific args/option parser for pull """ + # signature is different from parent as caller should not need to add usage/desc super(PullCLI, self).init_parser( usage='%prog -U <repository> [options] [<playbook.yml>]', desc="pulls playbooks from a VCS repo and executes them on target host") @@ -106,10 +135,12 @@ help='path to the directory to which Ansible will checkout the repository.') self.parser.add_argument('-U', '--url', dest='url', default=None, help='URL of the playbook repository') self.parser.add_argument('--full', dest='fullclone', action='store_true', help='Do a full clone, instead of a shallow one.') + # TODO: resolve conflict with check mode, added manually below self.parser.add_argument('-C', '--checkout', dest='checkout', help='branch/tag/commit to checkout. Defaults to behavior of repository module.') self.parser.add_argument('--accept-host-key', default=False, dest='accept_host_key', action='store_true', help='adds the hostkey for the repo url if not already added') + # Overloaded with adhoc ... but really passthrough to adhoc self.parser.add_argument('-m', '--module-name', dest='module_name', default=self.DEFAULT_REPO_TYPE, help='Repository module name, which ansible will use to check out the repo. Choices are %s. Default is %s.' % (self.REPO_CHOICES, self.DEFAULT_REPO_TYPE)) @@ -121,7 +152,7 @@ self.parser.add_argument('--track-subs', dest='tracksubs', default=False, action='store_true', help='submodules will track the latest changes. This is equivalent to specifying the --remote flag to git submodule update') # add a subset of the check_opts flag group manually, as the full set's - # shortcodes conflict with above --checkout/-C + # shortcodes conflict with above --checkout/-C, see to-do above self.parser.add_argument("--check", default=False, dest='check', action='store_true', help="don't make any changes; instead, try to predict some of the changes that may occur") self.parser.add_argument("--diff", default=C.DIFF_ALWAYS, dest='diff', action='store_true', @@ -177,7 +208,7 @@ limit_opts = 'localhost,127.0.0.1' base_opts = '-c local ' if context.CLIARGS['verbosity'] > 0: - base_opts += ' -%s' % ''.join(["v" for x in range(0, context.CLIARGS['verbosity'])]) + base_opts += ' -%s' % ''.join(["v" for dummy in range(0, context.CLIARGS['verbosity'])]) # Attempt to use the inventory passed in as an argument # It might not yet have been downloaded so use localhost as default @@ -250,16 +281,22 @@ # RUN the Checkout command display.debug("running ansible with VCS module to checkout repo") display.vvvv('EXEC: %s' % cmd) - rc, b_out, b_err = run_cmd(cmd, live=True) + rc, b_out, b_err = safe_output_env(run_cmd)(cmd, live=True) if rc != 0: if context.CLIARGS['force']: display.warning("Unable to update repository. Continuing with (forced) run of playbook.") else: return rc - elif context.CLIARGS['ifchanged'] and b'"changed": true' not in b_out: - display.display("Repository has not changed, quitting.") - return 0 + elif context.CLIARGS['ifchanged']: + # detect json/yaml/header, any count as 'changed' + for detect in (b'"changed": true', b"changed: True", b"| CHANGED =>"): + if detect in b_out: + break + else: + # no change, we bail + display.display(f"Repository has not changed, quitting: {b_out!r}") + return 0 playbook = self.select_playbook(context.CLIARGS['dest']) if playbook is None: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/lib/ansible/module_utils/ansible_release.py new/ansible_core-2.18.7/lib/ansible/module_utils/ansible_release.py --- old/ansible_core-2.18.6/lib/ansible/module_utils/ansible_release.py 2025-05-19 18:56:48.000000000 +0200 +++ new/ansible_core-2.18.7/lib/ansible/module_utils/ansible_release.py 2025-07-15 19:46:32.000000000 +0200 @@ -17,6 +17,6 @@ from __future__ import annotations -__version__ = '2.18.6' +__version__ = '2.18.7' __author__ = 'Ansible, Inc.' __codename__ = "Fool in the Rain" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/lib/ansible/modules/dnf5.py new/ansible_core-2.18.7/lib/ansible/modules/dnf5.py --- old/ansible_core-2.18.6/lib/ansible/modules/dnf5.py 2025-05-19 18:56:48.000000000 +0200 +++ new/ansible_core-2.18.7/lib/ansible/modules/dnf5.py 2025-07-15 19:46:32.000000000 +0200 @@ -355,7 +355,7 @@ libdnf5 = None # Through dnf5-5.2.12 all exceptions raised through swig became RuntimeError -LIBDNF5_ERROR = RuntimeError +LIBDNF5_ERRORS = RuntimeError def is_installed(base, spec): @@ -413,7 +413,9 @@ try: spec_nevra = next(iter(libdnf5.rpm.Nevra.parse(spec))) - except (LIBDNF5_ERROR, StopIteration): + except LIBDNF5_ERRORS: + return False + except StopIteration: return False spec_version = spec_nevra.get_version() @@ -505,7 +507,7 @@ os.environ["LANGUAGE"] = os.environ["LANG"] = locale global libdnf5 - global LIBDNF5_ERROR + global LIBDNF5_ERRORS has_dnf = True try: import libdnf5 # type: ignore[import] @@ -514,7 +516,7 @@ try: import libdnf5.exception # type: ignore[import-not-found] - LIBDNF5_ERROR = libdnf5.exception.Error + LIBDNF5_ERRORS = (libdnf5.exception.Error, libdnf5.exception.NonLibdnf5Exception) except (ImportError, AttributeError): pass @@ -560,15 +562,7 @@ if self.conf_file: conf.config_file_path = self.conf_file - try: - base.load_config() - except LIBDNF5_ERROR as e: - self.module.fail_json( - msg=str(e), - conf_file=self.conf_file, - failures=[], - rc=1, - ) + base.load_config() if self.releasever is not None: variables = base.get_vars() @@ -724,19 +718,13 @@ goal.add_install(spec, settings) elif self.state in {"absent", "removed"}: for spec in self.names: - try: - goal.add_remove(spec, settings) - except LIBDNF5_ERROR as e: - self.module.fail_json(msg=str(e), failures=[], rc=1) + goal.add_remove(spec, settings) if self.autoremove: for pkg in get_unneeded_pkgs(base): goal.add_rpm_remove(pkg, settings) goal.set_allow_erasing(self.allowerasing) - try: - transaction = goal.resolve() - except LIBDNF5_ERROR as e: - self.module.fail_json(msg=str(e), failures=[], rc=1) + transaction = goal.resolve() if transaction.get_problems(): failures = [] @@ -807,7 +795,11 @@ def main(): - Dnf5Module(AnsibleModule(**yumdnf_argument_spec)).run() + module = AnsibleModule(**yumdnf_argument_spec) + try: + Dnf5Module(module).run() + except LIBDNF5_ERRORS as e: + module.fail_json(msg=str(e), failures=[], rc=1) if __name__ == "__main__": diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/lib/ansible/modules/user.py new/ansible_core-2.18.7/lib/ansible/modules/user.py --- old/ansible_core-2.18.6/lib/ansible/modules/user.py 2025-05-19 18:56:48.000000000 +0200 +++ new/ansible_core-2.18.7/lib/ansible/modules/user.py 2025-07-15 19:46:32.000000000 +0200 @@ -490,6 +490,7 @@ import ctypes.util +from datetime import datetime import grp import calendar import os @@ -1279,11 +1280,16 @@ env=env) out_buffer = b'' err_buffer = b'' + first_prompt = b'Enter passphrase' + second_prompt = b'Enter same passphrase again' + prompt = first_prompt + start = datetime.now() + timeout = 900 while p.poll() is None: r_list = select.select([master_out_fd, master_err_fd], [], [], 1)[0] - first_prompt = b'Enter passphrase (empty for no passphrase):' - second_prompt = b'Enter same passphrase again' - prompt = first_prompt + now = datetime.now() + if (now - start).seconds > timeout: + return (1, '', f'Timeout after {timeout} while reading passphrase for SSH key') for fd in r_list: if fd == master_out_fd: chunk = os.read(master_out_fd, 10240) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/lib/ansible/playbook/task.py new/ansible_core-2.18.7/lib/ansible/playbook/task.py --- old/ansible_core-2.18.6/lib/ansible/playbook/task.py 2025-05-19 18:56:48.000000000 +0200 +++ new/ansible_core-2.18.7/lib/ansible/playbook/task.py 2025-07-15 19:46:32.000000000 +0200 @@ -137,9 +137,8 @@ def __repr__(self): ''' returns a human-readable representation of the task ''' if self.action in C._ACTION_META: - return "TASK: meta (%s)" % self.args['_raw_params'] - else: - return "TASK: %s" % self.get_name() + return "TASK: meta (%s)" % self.args.get('_raw_params') + return "TASK: %s" % self.get_name() def _preprocess_with_loop(self, ds, new_ds, k, v): ''' take a lookup plugin name and store it correctly ''' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/lib/ansible/plugins/filter/to_json.yml new/ansible_core-2.18.7/lib/ansible/plugins/filter/to_json.yml --- old/ansible_core-2.18.6/lib/ansible/plugins/filter/to_json.yml 2025-05-19 18:56:48.000000000 +0200 +++ new/ansible_core-2.18.7/lib/ansible/plugins/filter/to_json.yml 2025-07-15 19:46:32.000000000 +0200 @@ -23,8 +23,9 @@ default: True version_added: '2.9' allow_nan: - description: When V(False), strict adherence to float value limits of the JSON specifications, so C(nan), C(inf) and C(-inf) values will produce errors. - When V(True), JavaScript equivalents will be used (C(NaN), C(Infinity), C(-Infinity)). + description: + - When V(False), out-of-range float values C(nan), C(inf) and C(-inf) will result in an error. + - When V(True), out-of-range float values will be represented using their JavaScript equivalents, C(NaN), C(Infinity) and C(-Infinity). default: True type: bool check_circular: @@ -42,8 +43,11 @@ separators: description: The C(item) and C(key) separator to be used in the serialized output, default may change depending on O(indent) and Python version. - default: "(', ', ': ')" - type: tuple + default: + - ', ' + - ': ' + type: list + elements: str skipkeys: description: If V(True), keys that are not basic Python types will be skipped. default: False diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/lib/ansible/plugins/filter/to_nice_json.yml new/ansible_core-2.18.7/lib/ansible/plugins/filter/to_nice_json.yml --- old/ansible_core-2.18.6/lib/ansible/plugins/filter/to_nice_json.yml 2025-05-19 18:56:48.000000000 +0200 +++ new/ansible_core-2.18.7/lib/ansible/plugins/filter/to_nice_json.yml 2025-07-15 19:46:32.000000000 +0200 @@ -23,8 +23,9 @@ default: True version_added: '2.9' allow_nan: - description: When V(False), strict adherence to float value limits of the JSON specification, so C(nan), C(inf) and C(-inf) values will produce errors. - When V(True), JavaScript equivalents will be used (C(NaN), C(Infinity), C(-Infinity)). + description: + - When V(False), out-of-range float values C(nan), C(inf) and C(-inf) will result in an error. + - When V(True), out-of-range float values will be represented using their JavaScript equivalents, C(NaN), C(Infinity) and C(-Infinity). default: True type: bool check_circular: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/lib/ansible/plugins/list.py new/ansible_core-2.18.7/lib/ansible/plugins/list.py --- old/ansible_core-2.18.6/lib/ansible/plugins/list.py 2025-05-19 18:56:48.000000000 +0200 +++ new/ansible_core-2.18.7/lib/ansible/plugins/list.py 2025-07-15 19:46:32.000000000 +0200 @@ -42,7 +42,7 @@ return '.'.join(composite) -def _list_plugins_from_paths(ptype, dirs, collection, depth=0): +def _list_plugins_from_paths(ptype, dirs, collection, depth=0, docs=False): # TODO: update to use importlib.resources plugins = {} @@ -77,14 +77,15 @@ continue # actually recurse dirs - plugins.update(_list_plugins_from_paths(ptype, [to_native(full_path)], collection, depth=depth + 1)) + plugins.update(_list_plugins_from_paths(ptype, [to_native(full_path)], collection, depth=depth + 1, docs=docs)) else: if any([ plugin in C.IGNORE_FILES, # general files to ignore to_native(b_ext) in C.REJECT_EXTS, # general extensions to ignore - b_ext in (b'.yml', b'.yaml', b'.json'), # ignore docs files TODO: constant! + b_ext in (b'.yml', b'.yaml', b'.json'), # ignore docs files plugin in IGNORE.get(bkey, ()), # plugin in reject list os.path.islink(full_path), # skip aliases, author should document in 'aliases' field + not docs and b_ext in (b''), # ignore no ext when looking for docs files ]): continue @@ -147,7 +148,7 @@ # raise Exception('bad acr for %s, %s' % (collection, ptype)) - plugins.update(_list_plugins_from_paths(ptype, dirs, collection)) + plugins.update(_list_plugins_from_paths(ptype, dirs, collection, docs=True)) # return plugin and it's class object, None for those not verifiable or failing if ptype in ('module',): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/lib/ansible/plugins/lookup/password.py new/ansible_core-2.18.7/lib/ansible/plugins/lookup/password.py --- old/ansible_core-2.18.6/lib/ansible/plugins/lookup/password.py 2025-05-19 18:56:48.000000000 +0200 +++ new/ansible_core-2.18.7/lib/ansible/plugins/lookup/password.py 2025-07-15 19:46:32.000000000 +0200 @@ -126,6 +126,7 @@ elements: str """ +import contextlib import os import string import time @@ -269,15 +270,12 @@ b_pathdir = os.path.dirname(b_path) lockfile_name = to_bytes("%s.ansible_lockfile" % hashlib.sha1(b_path).hexdigest()) lockfile = os.path.join(b_pathdir, lockfile_name) - if not os.path.exists(lockfile) and b_path != to_bytes('/dev/null'): - try: - makedirs_safe(b_pathdir, mode=0o700) + if b_path != b'/dev/null': + makedirs_safe(b_pathdir, mode=0o700) + with contextlib.suppress(FileExistsError): fd = os.open(lockfile, os.O_CREAT | os.O_EXCL) os.close(fd) first_process = True - except OSError as e: - if e.strerror != 'File exists': - raise counter = 0 # if the lock is got by other process, wait until it's released diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/lib/ansible/release.py new/ansible_core-2.18.7/lib/ansible/release.py --- old/ansible_core-2.18.6/lib/ansible/release.py 2025-05-19 18:56:48.000000000 +0200 +++ new/ansible_core-2.18.7/lib/ansible/release.py 2025-07-15 19:46:32.000000000 +0200 @@ -17,6 +17,6 @@ from __future__ import annotations -__version__ = '2.18.6' +__version__ = '2.18.7' __author__ = 'Ansible, Inc.' __codename__ = "Fool in the Rain" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/pyproject.toml new/ansible_core-2.18.7/pyproject.toml --- old/ansible_core-2.18.6/pyproject.toml 2025-05-19 18:56:48.000000000 +0200 +++ new/ansible_core-2.18.7/pyproject.toml 2025-07-15 19:46:32.000000000 +0200 @@ -1,5 +1,5 @@ [build-system] -requires = ["setuptools >= 66.1.0, <= 80.7.1", "wheel == 0.45.1"] # lower bound to support controller Python versions, upper bound for latest version tested at release +requires = ["setuptools >= 66.1.0, <= 80.9.0", "wheel == 0.45.1"] # lower bound to support controller Python versions, upper bound for latest version tested at release build-backend = "setuptools.build_meta" [project] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/test/integration/targets/ansible-doc/library/bogus_facts new/ansible_core-2.18.7/test/integration/targets/ansible-doc/library/bogus_facts --- old/ansible_core-2.18.6/test/integration/targets/ansible-doc/library/bogus_facts 1970-01-01 01:00:00.000000000 +0100 +++ new/ansible_core-2.18.7/test/integration/targets/ansible-doc/library/bogus_facts 2025-07-15 19:46:32.000000000 +0200 @@ -0,0 +1,6 @@ +#!/bin/sh + +echo '{ + "changed": false, + "ansible_facts": {"nothing": "to report"}, +}' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/test/integration/targets/ansible-doc/library/bogus_facts.py new/ansible_core-2.18.7/test/integration/targets/ansible-doc/library/bogus_facts.py --- old/ansible_core-2.18.6/test/integration/targets/ansible-doc/library/bogus_facts.py 1970-01-01 01:00:00.000000000 +0100 +++ new/ansible_core-2.18.7/test/integration/targets/ansible-doc/library/bogus_facts.py 2025-07-15 19:46:32.000000000 +0200 @@ -0,0 +1,6 @@ +DOCUMENTATION = """ + module: bogus_facts + short_description: bad facts returned + version_added: historical + description: bogus facts for testing +""" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/test/integration/targets/ansible-doc/library/facts_one new/ansible_core-2.18.7/test/integration/targets/ansible-doc/library/facts_one --- old/ansible_core-2.18.6/test/integration/targets/ansible-doc/library/facts_one 1970-01-01 01:00:00.000000000 +0100 +++ new/ansible_core-2.18.7/test/integration/targets/ansible-doc/library/facts_one 2025-07-15 19:46:32.000000000 +0200 @@ -0,0 +1,6 @@ +#!/bin/sh + +echo '{ + "changed": false, + "ansible_facts": {"factsone": "from facts_one module"} +}' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/test/integration/targets/ansible-doc/library/facts_one.yml new/ansible_core-2.18.7/test/integration/targets/ansible-doc/library/facts_one.yml --- old/ansible_core-2.18.6/test/integration/targets/ansible-doc/library/facts_one.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/ansible_core-2.18.7/test/integration/targets/ansible-doc/library/facts_one.yml 2025-07-15 19:46:32.000000000 +0200 @@ -0,0 +1,5 @@ +DOCUMENTATION: + module: facts_one + short_description: random facts returned + version_added: historical + description: random facts for testing diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/test/integration/targets/ansible-doc/runme.sh new/ansible_core-2.18.7/test/integration/targets/ansible-doc/runme.sh --- old/ansible_core-2.18.6/test/integration/targets/ansible-doc/runme.sh 2025-05-19 18:56:48.000000000 +0200 +++ new/ansible_core-2.18.7/test/integration/targets/ansible-doc/runme.sh 2025-07-15 19:46:32.000000000 +0200 @@ -277,3 +277,9 @@ echo "testing without playbook dir, builtin should return" ansible-doc -t filter split -v 2>&1 |grep "${GREP_OPTS[@]}" -v histerical + +echo "test 'sidecar' for no extension module with .py doc" +[ "$(ansible-doc -M ./library -l ansible.legacy |grep -v 'UNDOCUMENTED' |grep -c bogus_facts)" == "1" ] + +echo "test 'sidecar' for no extension module with .yml doc" +[ "$(ansible-doc -M ./library -l ansible.legacy |grep -v 'UNDOCUMENTED' |grep -c facts_one)" == "1" ] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/test/integration/targets/ansible-pull/aliases new/ansible_core-2.18.7/test/integration/targets/ansible-pull/aliases --- old/ansible_core-2.18.6/test/integration/targets/ansible-pull/aliases 2025-05-19 18:56:48.000000000 +0200 +++ new/ansible_core-2.18.7/test/integration/targets/ansible-pull/aliases 2025-07-15 19:46:32.000000000 +0200 @@ -1,2 +1,3 @@ shippable/posix/group5 context/controller +needs/root diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/test/integration/targets/ansible-pull/cleanup.yml new/ansible_core-2.18.7/test/integration/targets/ansible-pull/cleanup.yml --- old/ansible_core-2.18.6/test/integration/targets/ansible-pull/cleanup.yml 2025-05-19 18:56:48.000000000 +0200 +++ new/ansible_core-2.18.7/test/integration/targets/ansible-pull/cleanup.yml 2025-07-15 19:46:32.000000000 +0200 @@ -1,6 +1,6 @@ - hosts: localhost vars: - git_install: '{{ lookup("file", lookup("env", "OUTPUT_DIR") + "/git_install.json") }}' + git_install: '{{ lookup("file", lookup("env", "OUTPUT_DIR") + "/git_install.json") | from_json }}' tasks: - name: remove unwanted packages package: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/test/integration/targets/ansible-pull/runme.sh new/ansible_core-2.18.7/test/integration/targets/ansible-pull/runme.sh --- old/ansible_core-2.18.6/test/integration/targets/ansible-pull/runme.sh 2025-05-19 18:56:48.000000000 +0200 +++ new/ansible_core-2.18.7/test/integration/targets/ansible-pull/runme.sh 2025-07-15 19:46:32.000000000 +0200 @@ -27,6 +27,23 @@ git commit -m "Initial commit." ) +function change_repo { + cd "${repo_dir}" + date > forced_change + git add forced_change + git commit -m "forced changed" + cd - +} + +function no_change_tests { + # test for https://github.com/ansible/ansible/issues/13688 + if grep MAGICKEYWORD "${temp_log}"; then + cat "${temp_log}" + echo "Ran the playbook, found MAGICKEYWORD in output." + exit 1 + fi +} + function pass_tests { # test for https://github.com/ansible/ansible/issues/13688 if ! grep MAGICKEYWORD "${temp_log}"; then @@ -91,3 +108,31 @@ # fail if we try do delete /var/tmp ANSIBLE_CONFIG='' ansible-pull -d var/tmp -U "${repo_dir}" --purge "$@" + +#### CHACHCHCHANGES! +echo 'setup for change detection' +ORIG_CONFIG="${ANSIBLE_CONFIG}" +unset ANSIBLE_CONFIG + +echo 'test no run on no changes' +ansible-pull -d "${pull_dir}" -U "${repo_dir}" --only-if-changed "$@" | tee "${temp_log}" +no_change_tests + +echo 'test run on changes' +change_repo +ansible-pull -d "${pull_dir}" -U "${repo_dir}" --only-if-changed "$@" | tee "${temp_log}" +pass_tests + +# test changed with non yaml result format, ensures we ignore callback or format changes for adhoc/change detection +echo 'test no run on no changes, yaml result format' +ANSIBLE_CALLBACK_RESULT_FORMAT='yaml' ansible-pull -d "${pull_dir}" -U "${repo_dir}" --only-if-changed "$@" | tee "${temp_log}" +no_change_tests + +echo 'test run on changes, yaml result format' +change_repo +ANSIBLE_CALLBACK_RESULT_FORMAT='yaml' ansible-pull -d "${pull_dir}" -U "${repo_dir}" --only-if-changed "$@" | tee "${temp_log}" +pass_tests + +if [ "${ORIG_CONFIG}" != "" ]; then + export ANSIBLE_CONFIG="${ORIG_CONFIG}" +fi diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/test/integration/targets/copy/tasks/acls.yml new/ansible_core-2.18.7/test/integration/targets/copy/tasks/acls.yml --- old/ansible_core-2.18.6/test/integration/targets/copy/tasks/acls.yml 2025-05-19 18:56:48.000000000 +0200 +++ new/ansible_core-2.18.7/test/integration/targets/copy/tasks/acls.yml 2025-07-15 19:46:32.000000000 +0200 @@ -3,6 +3,13 @@ apt: name: acl when: ansible_distribution in ('Ubuntu') + register: setup_acl + + - name: Install the acl package on RedHat + dnf: + name: acl + when: ansible_distribution in ('RedHat') + register: setup_acl - block: - name: Testing ACLs @@ -30,6 +37,18 @@ - "'other::r--' in acls.stdout_lines" always: + - name: Remove the acl package on Ubuntu + apt: + name: acl + state: absent + when: setup_acl is changed and ansible_distribution in ('Ubuntu') + + - name: Remove the acl package on RedHat + dnf: + name: acl + state: absent + when: setup_acl is changed and ansible_distribution in ('RedHat') + - name: Clean up file: path: "~/test.txt" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/test/integration/targets/dnf/tasks/dnf.yml new/ansible_core-2.18.7/test/integration/targets/dnf/tasks/dnf.yml --- old/ansible_core-2.18.6/test/integration/targets/dnf/tasks/dnf.yml 2025-05-19 18:56:48.000000000 +0200 +++ new/ansible_core-2.18.7/test/integration/targets/dnf/tasks/dnf.yml 2025-07-15 19:46:32.000000000 +0200 @@ -892,8 +892,6 @@ that: - enable_plugin_result is failed - disable_plugin_result is failed - - '"No matches were found for the following plugin name patterns while enabling libdnf5 plugins: " in enable_plugin_result.msg' - - '"No matches were found for the following plugin name patterns while disabling libdnf5 plugins: " in disable_plugin_result.msg' - - '"nonexisting" in enable_plugin_result.msg' - - '"nonexisting" in disable_plugin_result.msg' + - enable_plugin_result.msg is contains("'enable_plugin' requires python3-libdnf5 5.2.0.0+") + - disable_plugin_result.msg is contains("'disable_plugin' requires python3-libdnf5 5.2.0.0+") when: dnf5|default(false) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/test/integration/targets/dnf/tasks/gpg.yml new/ansible_core-2.18.7/test/integration/targets/dnf/tasks/gpg.yml --- old/ansible_core-2.18.6/test/integration/targets/dnf/tasks/gpg.yml 2025-05-19 18:56:48.000000000 +0200 +++ new/ansible_core-2.18.7/test/integration/targets/dnf/tasks/gpg.yml 2025-07-15 19:46:32.000000000 +0200 @@ -69,11 +69,10 @@ - "'is not signed' in res.msg" always: - - name: Remove rpm-sign and attr (and test package if it got installed) + - name: Remove rpm-sign and test package if it got installed dnf: name: - rpm-sign - - attr - "{{ pkg_name }}" state: absent diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/test/integration/targets/dnf/tasks/repo.yml new/ansible_core-2.18.7/test/integration/targets/dnf/tasks/repo.yml --- old/ansible_core-2.18.6/test/integration/targets/dnf/tasks/repo.yml 2025-05-19 18:56:48.000000000 +0200 +++ new/ansible_core-2.18.7/test/integration/targets/dnf/tasks/repo.yml 2025-07-15 19:46:32.000000000 +0200 @@ -629,3 +629,30 @@ loop: - provides-package - provided-package + +- name: Test failures occured during loading repositories are properly handled + vars: + repo_name: test-non-existing-gpgkey-file + block: + - yum_repository: + name: "{{ repo_name }}" + baseurl: "file://{{ repodir }}" + description: "{{ repo_name }}" + repo_gpgcheck: true + skip_if_unavailable: false + + - dnf: + name: dinginessentail + enablerepo: "{{ repo_name }}" + disablerepo: "*" + ignore_errors: true + register: r + + - assert: + that: + - r is failed + - r.msg is contains("Couldn't open file") or r.msg is contains("Failed to download metadata") + always: + - file: + name: /etc/yum.repos.d/{{ repo_name }}.repo + state: absent diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/test/integration/targets/dnf5/playbook.yml new/ansible_core-2.18.7/test/integration/targets/dnf5/playbook.yml --- old/ansible_core-2.18.6/test/integration/targets/dnf5/playbook.yml 2025-05-19 18:56:48.000000000 +0200 +++ new/ansible_core-2.18.7/test/integration/targets/dnf5/playbook.yml 2025-07-15 19:46:32.000000000 +0200 @@ -1,9 +1,7 @@ - hosts: localhost tasks: - block: - - command: "dnf install -y 'dnf-command(copr)'" - - command: dnf copr enable -y rpmsoftwaremanagement/dnf-nightly - - command: dnf install -y -x condor python3-libdnf5 + - command: dnf install -y python3-libdnf5 - include_role: name: dnf diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/test/integration/targets/iptables/tasks/main.yml new/ansible_core-2.18.7/test/integration/targets/iptables/tasks/main.yml --- old/ansible_core-2.18.6/test/integration/targets/iptables/tasks/main.yml 2025-05-19 18:56:48.000000000 +0200 +++ new/ansible_core-2.18.7/test/integration/targets/iptables/tasks/main.yml 2025-07-15 19:46:32.000000000 +0200 @@ -32,5 +32,7 @@ package: name: iptables state: present + # prevent attempts to upgrade the kernel and install kernel modules for a non-running kernel version + exclude: "{{ 'kernel-core' if ansible_distribution == 'RedHat' else omit }}" - import_tasks: chain_management.yml diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/test/integration/targets/lineinfile/tasks/acls.yml new/ansible_core-2.18.7/test/integration/targets/lineinfile/tasks/acls.yml --- old/ansible_core-2.18.6/test/integration/targets/lineinfile/tasks/acls.yml 2025-05-19 18:56:48.000000000 +0200 +++ new/ansible_core-2.18.7/test/integration/targets/lineinfile/tasks/acls.yml 2025-07-15 19:46:32.000000000 +0200 @@ -5,6 +5,12 @@ when: ansible_distribution in ('Ubuntu') register: setup_acl + - name: Install the acl package on RedHat + dnf: + name: acl + when: ansible_distribution in ('RedHat') + register: setup_acl + - name: Create file copy: content: "TEST" @@ -46,7 +52,13 @@ apt: name: acl state: absent - when: setup_acl is changed + when: setup_acl is changed and ansible_distribution in ('Ubuntu') + + - name: Remove the acl package on RedHat + dnf: + name: acl + state: absent + when: setup_acl is changed and ansible_distribution in ('RedHat') - name: Clean up file: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/test/integration/targets/prepare_http_tests/tasks/default.yml new/ansible_core-2.18.7/test/integration/targets/prepare_http_tests/tasks/default.yml --- old/ansible_core-2.18.6/test/integration/targets/prepare_http_tests/tasks/default.yml 2025-05-19 18:56:48.000000000 +0200 +++ new/ansible_core-2.18.7/test/integration/targets/prepare_http_tests/tasks/default.yml 2025-07-15 19:46:32.000000000 +0200 @@ -1,5 +1,5 @@ - name: RedHat - Enable the dynamic CA configuration feature - command: update-ca-trust force-enable + command: update-ca-trust when: ansible_os_family == 'RedHat' and ansible_distribution != "Fedora" - name: RedHat - Retrieve test cacert diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/test/integration/targets/rpm_key/aliases new/ansible_core-2.18.7/test/integration/targets/rpm_key/aliases --- old/ansible_core-2.18.6/test/integration/targets/rpm_key/aliases 2025-05-19 18:56:48.000000000 +0200 +++ new/ansible_core-2.18.7/test/integration/targets/rpm_key/aliases 2025-07-15 19:46:32.000000000 +0200 @@ -1,2 +1,3 @@ destructive shippable/posix/group1 +needs/root diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/test/integration/targets/rpm_key/tasks/main.yaml new/ansible_core-2.18.7/test/integration/targets/rpm_key/tasks/main.yaml --- old/ansible_core-2.18.6/test/integration/targets/rpm_key/tasks/main.yaml 2025-05-19 18:56:48.000000000 +0200 +++ new/ansible_core-2.18.7/test/integration/targets/rpm_key/tasks/main.yaml 2025-07-15 19:46:32.000000000 +0200 @@ -1,2 +1,34 @@ - - include_tasks: 'rpm_key.yaml' - when: ansible_os_family == "RedHat" + - when: ansible_os_family == "RedHat" + block: + + - name: List the installed GPG keys + shell: rpm -q gpg-pubkey | sort + register: list_of_pubkeys + + - name: Retrieve the installed GPG keys + command: rpm -q --qf %{description} gpg-pubkey + register: pubkeys + + - name: Save the retrieved GPG keys to a file + copy: + content: "{{ pubkeys['stdout'] }}" + dest: "{{ remote_tmp_dir + '/pubkeys' }}" + mode: 0600 + + - include_tasks: rpm_key.yaml + + always: + + - name: Remove all GPG keys from key ring + shell: rpm -q gpg-pubkey | xargs rpm -e + + - name: Restore the previously installed GPG keys + command: rpm --import {{ (remote_tmp_dir + '/pubkeys') | quote }} + + - name: List the installed GPG keys + shell: rpm -q gpg-pubkey | sort + register: new_list_of_pubkeys + + - name: Verify the GPG keys have been restored + assert: + that: list_of_pubkeys["stdout"] == new_list_of_pubkeys["stdout"] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/test/integration/targets/rpm_key/tasks/rpm_key.yaml new/ansible_core-2.18.7/test/integration/targets/rpm_key/tasks/rpm_key.yaml --- old/ansible_core-2.18.6/test/integration/targets/rpm_key/tasks/rpm_key.yaml 2025-05-19 18:56:48.000000000 +0200 +++ new/ansible_core-2.18.7/test/integration/targets/rpm_key/tasks/rpm_key.yaml 2025-07-15 19:46:32.000000000 +0200 @@ -1,158 +1,137 @@ ---- -# -# Save initial state -# -- name: Retrieve a list of gpg keys are installed for package checking - shell: 'rpm -q gpg-pubkey | sort' - register: list_of_pubkeys - -- name: Retrieve the gpg keys used to verify packages - command: 'rpm -q --qf %{description} gpg-pubkey' - register: pubkeys - -- name: Save gpg keys to a file - copy: - content: "{{ pubkeys['stdout'] }}\n" - dest: '{{ remote_tmp_dir }}/pubkeys' - mode: 0600 - -# -# Tests start -# -- name: download EPEL GPG key +- name: Download test key get_url: - url: https://ci-files.testing.ansible.com/test/integration/targets/rpm_key/RPM-GPG-KEY-EPEL-7 - dest: /tmp/RPM-GPG-KEY-EPEL-7 + url: "{{ test_key_url }}" + dest: "{{ test_key_path }}" -- name: download sl rpm +- name: Download test RPM get_url: - url: https://ci-files.testing.ansible.com/test/integration/targets/rpm_key/sl-5.02-1.el7.x86_64.rpm - dest: /tmp/sl.rpm + url: "{{ test_rpm_url }}" + dest: "{{ test_rpm_path }}" -- name: remove EPEL GPG key from keyring +- name: Remove test key from keyring rpm_key: state: absent - key: /tmp/RPM-GPG-KEY-EPEL-7 + key: "{{ test_key_path }}" -- name: check GPG signature of sl. Should fail - shell: "rpm --checksig /tmp/sl.rpm" - register: sl_check +- name: Verify checking signature of RPM fails + shell: rpm --checksig {{ test_rpm_path | quote }} + register: checksig ignore_errors: yes -- name: confirm that signature check failed +- name: Confirm that signature check failed assert: that: - - "'MISSING KEYS' in sl_check.stdout or 'SIGNATURES NOT OK' in sl_check.stdout" - - "sl_check.failed" + - checksig.stdout is contains 'SIGNATURES NOT OK' + - checksig.failed -- name: remove EPEL GPG key from keyring (idempotent) +- name: Remove test key from keyring (idempotent) rpm_key: state: absent - key: /tmp/RPM-GPG-KEY-EPEL-7 + key: "{{ test_key_path }}" register: idempotent_test -- name: check idempotence +- name: Check idempotence assert: - that: "not idempotent_test.changed" + that: idempotent_test is not changed -- name: add EPEL GPG key to key ring +- name: Add test key to key ring rpm_key: state: present - key: /tmp/RPM-GPG-KEY-EPEL-7 + key: "{{ test_key_path }}" -- name: add EPEL GPG key to key ring (idempotent) +- name: Add test key to key ring (idempotent) rpm_key: state: present - key: /tmp/RPM-GPG-KEY-EPEL-7 + key: "{{ test_key_path }}" register: key_idempotence -- name: verify idempotence +- name: Verify idempotence assert: - that: "not key_idempotence.changed" + that: key_idempotence is not changed -- name: check GPG signature of sl. Should return okay - shell: "rpm --checksig /tmp/sl.rpm" - register: sl_check +- name: Check signature of RPM + shell: rpm --checksig {{ test_rpm_path | quote }} + register: checksig -- name: confirm that signature check succeeded +- name: Confirm that signature check succeeded assert: - that: "'rsa sha1 (md5) pgp md5 OK' in sl_check.stdout or 'digests signatures OK' in sl_check.stdout" + that: checksig.stdout is contains 'digests signatures OK' -- name: remove GPG key from url +- name: Remove test key via url rpm_key: state: absent - key: https://ci-files.testing.ansible.com/test/integration/targets/rpm_key/RPM-GPG-KEY-EPEL-7 + key: "{{ test_key_url }}" - name: Confirm key is missing - shell: "rpm --checksig /tmp/sl.rpm" - register: sl_check + shell: rpm --checksig {{ test_rpm_path | quote }} + register: checksig ignore_errors: yes -- name: confirm that signature check failed +- name: Confirm that signature check failed assert: that: - - "'MISSING KEYS' in sl_check.stdout or 'SIGNATURES NOT OK' in sl_check.stdout" - - "sl_check.failed" + - checksig.stdout is contains 'SIGNATURES NOT OK' + - checksig.failed -- name: add GPG key from url +- name: Add test key from url rpm_key: state: present - key: https://ci-files.testing.ansible.com/test/integration/targets/rpm_key/RPM-GPG-KEY-EPEL-7 + key: "{{ test_key_url }}" -- name: check GPG signature of sl. Should return okay - shell: "rpm --checksig /tmp/sl.rpm" - register: sl_check +- name: Check signature of RPM + shell: rpm --checksig {{ test_rpm_path | quote }} + register: checksig -- name: confirm that signature check succeeded +- name: Confirm that signature check succeeded assert: - that: "'rsa sha1 (md5) pgp md5 OK' in sl_check.stdout or 'digests signatures OK' in sl_check.stdout" + that: checksig.stdout is contains 'digests signatures OK' -- name: remove all keys from key ring - shell: "rpm -q gpg-pubkey | xargs rpm -e" +- name: Remove all keys from key ring + shell: rpm -q gpg-pubkey | xargs rpm -e -- name: add very first key on system +- name: Add very first key on system rpm_key: state: present - key: https://ci-files.testing.ansible.com/test/integration/targets/rpm_key/RPM-GPG-KEY-EPEL-7 + key: "{{ test_key_url }}" -- name: check GPG signature of sl. Should return okay - shell: "rpm --checksig /tmp/sl.rpm" - register: sl_check +- name: Check GPG signature of RPM + shell: rpm --checksig {{ test_rpm_path | quote }} + register: checksig -- name: confirm that signature check succeeded +- name: Confirm that signature check succeeded assert: - that: "'rsa sha1 (md5) pgp md5 OK' in sl_check.stdout or 'digests signatures OK' in sl_check.stdout" + that: checksig.stdout is contains 'digests signatures OK' -- name: get keyid - shell: "rpm -q gpg-pubkey | head -n 1 | xargs rpm -q --qf %{version}" +- name: Get keyid + shell: rpm -q gpg-pubkey | head -n 1 | xargs rpm -q --qf %{version} register: key_id -- name: remove GPG key using keyid +- name: Remove test key using keyid rpm_key: state: absent key: "{{ key_id.stdout }}" register: remove_keyid - failed_when: remove_keyid.changed == false + failed_when: not remove_keyid.changed -- name: remove GPG key using keyid (idempotent) +- name: Remove test key using keyid (idempotent) rpm_key: state: absent key: "{{ key_id.stdout }}" register: key_id_idempotence -- name: verify idempotent (key_id) +- name: Verify idempotent (key_id) assert: - that: "not key_id_idempotence.changed" + that: key_id_idempotence is not changed -- name: add very first key on system again +- name: Add very first key on system again rpm_key: state: present - key: https://ci-files.testing.ansible.com/test/integration/targets/rpm_key/RPM-GPG-KEY-EPEL-7 + key: "{{ test_key_url }}" - name: Issue 20325 - Verify fingerprint of key, invalid fingerprint - EXPECTED FAILURE rpm_key: - key: https://ci-files.testing.ansible.com/test/integration/targets/rpm_key/RPM-GPG-KEY.dag - fingerprint: 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 + key: "{{ sub_key_url }}" + fingerprint: "{{ invalid_fingerprint }}" register: result failed_when: result is success @@ -161,12 +140,12 @@ that: - result is success - result is not changed - - "'does not match any key fingerprints' in result.msg" + - result.msg is contains 'does not match any key fingerprints' - name: Issue 20325 - Verify fingerprint of key, valid fingerprint rpm_key: - key: https://ci-files.testing.ansible.com/test/integration/targets/rpm_key/RPM-GPG-KEY.dag - fingerprint: EBC6 E12C 62B1 C734 026B 2122 A20E 5214 6B8D 79E6 + key: "{{ sub_key_url }}" + fingerprint: "{{ primary_fingerprint }}" register: result - name: Issue 20325 - Assert Verify fingerprint of key, valid fingerprint @@ -177,8 +156,8 @@ - name: Issue 20325 - Verify fingerprint of key, valid fingerprint - Idempotent check rpm_key: - key: https://ci-files.testing.ansible.com/test/integration/targets/rpm_key/RPM-GPG-KEY.dag - fingerprint: EBC6 E12C 62B1 C734 026B 2122 A20E 5214 6B8D 79E6 + key: "{{ sub_key_url }}" + fingerprint: "{{ primary_fingerprint }}" register: result - name: Issue 20325 - Assert Verify fingerprint of key, valid fingerprint - Idempotent check @@ -188,13 +167,14 @@ - result is not changed # Reset to test subkey validation -- name: remove all keys from key ring - shell: "rpm -q gpg-pubkey | xargs rpm -e" + +- name: Remove all keys from key ring + shell: rpm -q gpg-pubkey | xargs rpm -e - name: Verify fingerprint of subkey, valid fingerprint rpm_key: - key: https://ci-files.testing.ansible.com/test/integration/targets/rpm_key/RPM-GPG-KEY.dag - fingerprint: 19B7 913E 6284 8E3F 4D78 D6B4 ECD9 1AB2 2EB6 8D86 + key: "{{ sub_key_url }}" + fingerprint: "{{ sub_key_fingerprint }}" register: result - name: Assert Verify fingerprint of key, valid fingerprint @@ -205,8 +185,8 @@ - name: Verify fingerprint of subkey, valid fingerprint - Idempotent check rpm_key: - key: https://ci-files.testing.ansible.com/test/integration/targets/rpm_key/RPM-GPG-KEY.dag - fingerprint: 19B7 913E 6284 8E3F 4D78 D6B4 ECD9 1AB2 2EB6 8D86 + key: "{{ sub_key_url }}" + fingerprint: "{{ sub_key_fingerprint }}" register: result - name: Assert Verify fingerprint of subkey, valid fingerprint - Idempotent check @@ -216,15 +196,16 @@ - result is not changed # Reset to test multi-key validation -- name: remove all keys from key ring - shell: "rpm -q gpg-pubkey | xargs rpm -e" + +- name: Remove all keys from key ring + shell: rpm -q gpg-pubkey | xargs rpm -e - name: Verify fingerprint of primary and subkey, valid fingerprint rpm_key: - key: https://ci-files.testing.ansible.com/test/integration/targets/rpm_key/RPM-GPG-KEY.dag + key: "{{ sub_key_url }}" fingerprint: - - 19B7 913E 6284 8E3F 4D78 D6B4 ECD9 1AB2 2EB6 8D86 - - EBC6 E12C 62B1 C734 026B 2122 A20E 5214 6B8D 79E6 + - "{{ primary_fingerprint }}" + - "{{ sub_key_fingerprint }}" register: result - name: Assert Verify fingerprint of primary and subkey, valid fingerprint @@ -235,10 +216,10 @@ - name: Verify fingerprint of primary and subkey, valid fingerprint - Idempotent check rpm_key: - key: https://ci-files.testing.ansible.com/test/integration/targets/rpm_key/RPM-GPG-KEY.dag + key: "{{ sub_key_url }}" fingerprint: - - 19B7 913E 6284 8E3F 4D78 D6B4 ECD9 1AB2 2EB6 8D86 - - EBC6 E12C 62B1 C734 026B 2122 A20E 5214 6B8D 79E6 + - "{{ primary_fingerprint }}" + - "{{ sub_key_fingerprint }}" register: result - name: Assert Verify fingerprint of primary and subkey, valid fingerprint - Idempotent check @@ -246,22 +227,3 @@ that: - result is success - result is not changed - - -# -# Cleanup -# -- name: remove all keys from key ring - shell: "rpm -q gpg-pubkey | xargs rpm -e" - -- name: Restore the gpg keys normally installed on the system - command: 'rpm --import {{ remote_tmp_dir }}/pubkeys' - -- name: Retrieve a list of gpg keys are installed for package checking - shell: 'rpm -q gpg-pubkey | sort' - register: new_list_of_pubkeys - -- name: Confirm that we've restored all the pubkeys - assert: - that: - - 'list_of_pubkeys["stdout"] == new_list_of_pubkeys["stdout"]' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/test/integration/targets/rpm_key/vars/main.yml new/ansible_core-2.18.7/test/integration/targets/rpm_key/vars/main.yml --- old/ansible_core-2.18.6/test/integration/targets/rpm_key/vars/main.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/ansible_core-2.18.7/test/integration/targets/rpm_key/vars/main.yml 2025-07-15 19:46:32.000000000 +0200 @@ -0,0 +1,8 @@ +test_key_url: https://ci-files.testing.ansible.com/test/integration/targets/rpm_key/RPM-GPG-KEY-EPEL-10 +test_key_path: "{{ remote_tmp_dir + '/RPM-GPG-KEY-EPEL-10' }}" +test_rpm_url: https://ci-files.testing.ansible.com/test/integration/targets/rpm_key/scitokens-cpp-devel-1.1.3-2.el10_1.x86_64.rpm +test_rpm_path: "{{ remote_tmp_dir + '/test.rpm' }}" +sub_key_url: https://ci-files.testing.ansible.com/test/integration/targets/rpm_key/openbao-gpg-pub-20240618.asc +invalid_fingerprint: 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 +primary_fingerprint: 66D1 5FDD 8728 7219 C8E1 5478 D200 CD70 2853 E6D0 +sub_key_fingerprint: E617 DCD4 065C 2AFC 0B2C F7A7 BA8B C08C 0F69 1F94 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/test/integration/targets/setup_paramiko/install-RedHat-10-python-3.yml new/ansible_core-2.18.7/test/integration/targets/setup_paramiko/install-RedHat-10-python-3.yml --- old/ansible_core-2.18.6/test/integration/targets/setup_paramiko/install-RedHat-10-python-3.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/ansible_core-2.18.7/test/integration/targets/setup_paramiko/install-RedHat-10-python-3.yml 2025-07-15 19:46:32.000000000 +0200 @@ -0,0 +1,9 @@ +- name: Setup remote constraints + include_tasks: setup-remote-constraints.yml +- name: Install Paramiko for Python 3 on RHEL 10 + pip: # no python3-paramiko package exists for RHEL 10 + name: paramiko + extra_args: "-c {{ remote_constraints }}" + +- name: Drop the crypto-policy to LEGACY for these tests + command: update-crypto-policies --set LEGACY diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/test/integration/targets/setup_paramiko/uninstall-RedHat-10-python-3.yml new/ansible_core-2.18.7/test/integration/targets/setup_paramiko/uninstall-RedHat-10-python-3.yml --- old/ansible_core-2.18.6/test/integration/targets/setup_paramiko/uninstall-RedHat-10-python-3.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/ansible_core-2.18.7/test/integration/targets/setup_paramiko/uninstall-RedHat-10-python-3.yml 2025-07-15 19:46:32.000000000 +0200 @@ -0,0 +1,7 @@ +- name: Uninstall Paramiko for Python 3 on RHEL 10 + pip: # no python3-paramiko package exists for RHEL 10 + name: paramiko + state: absent + +- name: Revert the crypto-policy back to DEFAULT + command: update-crypto-policies --set DEFAULT diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/test/lib/ansible_test/_data/completion/remote.txt new/ansible_core-2.18.7/test/lib/ansible_test/_data/completion/remote.txt --- old/ansible_core-2.18.6/test/lib/ansible_test/_data/completion/remote.txt 2025-05-19 18:56:48.000000000 +0200 +++ new/ansible_core-2.18.7/test/lib/ansible_test/_data/completion/remote.txt 2025-07-15 19:46:32.000000000 +0200 @@ -8,6 +8,7 @@ macos/14.3 python=3.11 python_dir=/usr/local/bin become=sudo provider=parallels arch=x86_64 macos python_dir=/usr/local/bin become=sudo provider=parallels arch=x86_64 rhel/9.4 python=3.9,3.12 become=sudo provider=aws arch=x86_64 +rhel/10.0 python=3.12 become=sudo provider=aws arch=x86_64 rhel become=sudo provider=aws arch=x86_64 ubuntu/22.04 python=3.10 become=sudo provider=aws arch=x86_64 ubuntu/24.04 python=3.12 become=sudo provider=aws arch=x86_64 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/test/lib/ansible_test/_internal/classification/python.py new/ansible_core-2.18.7/test/lib/ansible_test/_internal/classification/python.py --- old/ansible_core-2.18.6/test/lib/ansible_test/_internal/classification/python.py 2025-05-19 18:56:48.000000000 +0200 +++ new/ansible_core-2.18.7/test/lib/ansible_test/_internal/classification/python.py 2025-07-15 19:46:32.000000000 +0200 @@ -220,6 +220,12 @@ else: parts = module.split('.') + if path.endswith('/__init__.py'): + # Ensure the correct relative module is calculated for both not_init.py and __init__.py: + # a/b/not_init.py -> a.b.not_init # used as-is + # a/b/__init__.py -> a.b # needs "__init__" part appended to ensure relative imports work + parts.append('__init__') + if level >= len(parts): display.warning('Cannot resolve relative import "%s%s" above module "%s" at %s:%d' % ('.' * level, name, module, path, lineno)) absolute_name = 'relative.abovelevel' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/test/lib/ansible_test/_util/target/setup/bootstrap.sh new/ansible_core-2.18.7/test/lib/ansible_test/_util/target/setup/bootstrap.sh --- old/ansible_core-2.18.6/test/lib/ansible_test/_util/target/setup/bootstrap.sh 2025-05-19 18:56:48.000000000 +0200 +++ new/ansible_core-2.18.7/test/lib/ansible_test/_util/target/setup/bootstrap.sh 2025-07-15 19:46:32.000000000 +0200 @@ -292,10 +292,41 @@ done } +bootstrap_remote_rhel_10() +{ + py_pkg_prefix="python3" + + packages=" + gcc + ${py_pkg_prefix}-devel + ${py_pkg_prefix}-pip + " + + if [ "${controller}" ]; then + packages=" + ${packages} + ${py_pkg_prefix}-cryptography + ${py_pkg_prefix}-jinja2 + ${py_pkg_prefix}-packaging + ${py_pkg_prefix}-pyyaml + ${py_pkg_prefix}-resolvelib + " + fi + + while true; do + # shellcheck disable=SC2086 + dnf install -q -y ${packages} \ + && break + echo "Failed to install packages. Sleeping before trying again..." + sleep 10 + done +} + bootstrap_remote_rhel() { case "${platform_version}" in 9.*) bootstrap_remote_rhel_9 ;; + 10.*) bootstrap_remote_rhel_10 ;; esac } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/test/sanity/ignore.txt new/ansible_core-2.18.7/test/sanity/ignore.txt --- old/ansible_core-2.18.6/test/sanity/ignore.txt 2025-05-19 18:56:48.000000000 +0200 +++ new/ansible_core-2.18.7/test/sanity/ignore.txt 2025-07-15 19:46:32.000000000 +0200 @@ -61,6 +61,8 @@ lib/ansible/plugins/callback/__init__.py pylint:arguments-renamed lib/ansible/plugins/inventory/advanced_host_list.py pylint:arguments-renamed lib/ansible/plugins/inventory/host_list.py pylint:arguments-renamed +test/integration/targets/ansible-doc/library/bogus_facts shebang +test/integration/targets/ansible-doc/library/facts_one shebang test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/tests/integration/targets/hello/files/bad.py pylint:ansible-bad-function # ignore, required for testing test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/tests/integration/targets/hello/files/bad.py pylint:ansible-bad-import-from # ignore, required for testing test/integration/targets/ansible-test-sanity/ansible_collections/ns/col/tests/integration/targets/hello/files/bad.py pylint:ansible-bad-import # ignore, required for testing diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.18.6/test/units/plugins/lookup/test_password.py new/ansible_core-2.18.7/test/units/plugins/lookup/test_password.py --- old/ansible_core-2.18.6/test/units/plugins/lookup/test_password.py 2025-05-19 18:56:48.000000000 +0200 +++ new/ansible_core-2.18.7/test/units/plugins/lookup/test_password.py 2025-07-15 19:46:32.000000000 +0200 @@ -466,11 +466,16 @@ @patch('time.sleep') def test_lock_been_held(self, mock_sleep): # pretend the lock file is here - password.os.path.exists = lambda x: True - with pytest.raises(AnsibleError): - with patch.object(builtins, 'open', mock_open(read_data=b'hunter42 salt=87654321\n')) as m: - # should timeout here - self.password_lookup.run([u'/path/to/somewhere chars=anything'], None) + def _already_exists(*args, **kwargs): + raise FileExistsError("The lock is busy, wait and try again.") + + with ( + pytest.raises(AnsibleError, match='^Password lookup cannot get the lock in 7 seconds.*'), + patch.object(password.os, 'open', _already_exists), + patch.object(password.os.path, 'exists', lambda *args, **kwargs: True), + ): + # should timeout here + self.password_lookup.run([u'/path/to/somewhere chars=anything'], None) def test_lock_not_been_held(self): # pretend now there is password file but no lock ++++++ ansible_core-2.18.6.tar.gz.sha256 -> ansible_core-2.18.7.tar.gz.sha256 ++++++ --- /work/SRC/openSUSE:Factory/ansible-core/ansible_core-2.18.6.tar.gz.sha256 2025-05-20 17:04:07.337555226 +0200 +++ /work/SRC/openSUSE:Factory/.ansible-core.new.7373/ansible_core-2.18.7.tar.gz.sha256 2025-07-16 17:36:21.174960424 +0200 @@ -1 +1 @@ -25bb20ce1516a1b7307831b263cef684043b3720711466bd9d4164e5fd576557 ansible_core-2.18.6.tar.gz +1a129bf9fcd5dca2b17e83ce77147ee2fbc3c51a4958970152897cc5b6d0aae7 ansible_core-2.18.7.tar.gz