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 2024-09-16 17:40:37 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/ansible-core (Old) and /work/SRC/openSUSE:Factory/.ansible-core.new.29891 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ansible-core" Mon Sep 16 17:40:37 2024 rev:32 rq:1200966 version:2.17.4 Changes: -------- --- /work/SRC/openSUSE:Factory/ansible-core/ansible-core.changes 2024-08-15 09:58:44.496008287 +0200 +++ /work/SRC/openSUSE:Factory/.ansible-core.new.29891/ansible-core.changes 2024-09-16 17:40:50.251501636 +0200 @@ -1,0 +2,38 @@ +Wed Sep 11 05:24:58 UTC 2024 - Johannes Kastl <opensuse_buildserv...@ojkastl.de> + +- update to 2.17.4: + https://github.com/ansible/ansible/blob/v2.17.4/changelogs/CHANGELOG-v2.17.rst + * Bugfixes + - Fix SemanticVersion.parse() to store the version string so + that __repr__ reports it instead of None (#83831). + - Fix an issue where registered variable was not available for + templating in loop_control.label on skipped looped tasks + (#83619) + - Fix for meta tasks breaking host/fork affinity with + host_pinned strategy (#83294) + - Fix using the current task's directory for looking up + relative paths within roles (#82695). + - atomic_move - fix using the setgid bit on the parent + directory when creating files (#46742, #67177). + - connection plugins using the 'extras' option feature would + need variables to match the plugin's loaded name, sometimes + requiring fqcn, which is not the same as the + documented/declared/expected variables. Now we fall back to + the 'basename' of the fqcn, but plugin authors can still set + the expected value directly. + - csvfile lookup - give an error when no search term is + provided using modern config syntax (#83689). + - include_tasks - Display location when attempting to load a + task list where include_* did not specify any value - #83874 + - powershell - Improve CLIXML decoding to decode all control + characters and unicode characters that are encoded as + surrogate pairs. + - psrp - Fix bug when attempting to fetch a file path that + contains special glob characters like [] + - runtime-metadata sanity test - do not crash on deprecations + if galaxy.yml contains an empty version field (#83831). + - ssh - Fix bug when attempting to fetch a file path with + characters that should be quoted when using the piped + transfer method + +------------------------------------------------------------------- Old: ---- ansible_core-2.17.3.tar.gz ansible_core-2.17.3.tar.gz.sha256 New: ---- ansible_core-2.17.4.tar.gz ansible_core-2.17.4.tar.gz.sha256 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ ansible-core.spec ++++++ --- /var/tmp/diff_new_pack.4O19u8/_old 2024-09-16 17:40:51.503553859 +0200 +++ /var/tmp/diff_new_pack.4O19u8/_new 2024-09-16 17:40:51.507554025 +0200 @@ -38,7 +38,7 @@ %endif Name: ansible-core -Version: 2.17.3 +Version: 2.17.4 Release: 0 Summary: Radically simple IT automation License: GPL-3.0-or-later ++++++ ansible_core-2.17.3.tar.gz -> ansible_core-2.17.4.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/PKG-INFO new/ansible_core-2.17.4/PKG-INFO --- old/ansible_core-2.17.3/PKG-INFO 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/PKG-INFO 2024-09-09 21:26:24.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: ansible-core -Version: 2.17.3 +Version: 2.17.4 Summary: Radically simple IT automation Home-page: https://ansible.com/ Author: Ansible, Inc. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/changelogs/CHANGELOG-v2.17.rst new/ansible_core-2.17.4/changelogs/CHANGELOG-v2.17.rst --- old/ansible_core-2.17.3/changelogs/CHANGELOG-v2.17.rst 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/changelogs/CHANGELOG-v2.17.rst 2024-09-09 21:26:24.000000000 +0200 @@ -4,6 +4,31 @@ .. contents:: Topics +v2.17.4 +======= + +Release Summary +--------------- + +| Release Date: 2024-09-09 +| `Porting Guide <https://docs.ansible.com/ansible-core/2.17/porting_guides/porting_guide_core_2.17.html>`__ + +Bugfixes +-------- + +- Fix ``SemanticVersion.parse()`` to store the version string so that ``__repr__`` reports it instead of ``None`` (https://github.com/ansible/ansible/pull/83831). +- Fix an issue where registered variable was not available for templating in ``loop_control.label`` on skipped looped tasks (https://github.com/ansible/ansible/issues/83619) +- Fix for ``meta`` tasks breaking host/fork affinity with ``host_pinned`` strategy (https://github.com/ansible/ansible/issues/83294) +- Fix using the current task's directory for looking up relative paths within roles (https://github.com/ansible/ansible/issues/82695). +- atomic_move - fix using the setgid bit on the parent directory when creating files (https://github.com/ansible/ansible/issues/46742, https://github.com/ansible/ansible/issues/67177). +- connection plugins using the 'extras' option feature would need variables to match the plugin's loaded name, sometimes requiring fqcn, which is not the same as the documented/declared/expected variables. Now we fall back to the 'basename' of the fqcn, but plugin authors can still set the expected value directly. +- csvfile lookup - give an error when no search term is provided using modern config syntax (https://github.com/ansible/ansible/issues/83689). +- include_tasks - Display location when attempting to load a task list where ``include_*`` did not specify any value - https://github.com/ansible/ansible/issues/83874 +- powershell - Improve CLIXML decoding to decode all control characters and unicode characters that are encoded as surrogate pairs. +- psrp - Fix bug when attempting to fetch a file path that contains special glob characters like ``[]`` +- runtime-metadata sanity test - do not crash on deprecations if ``galaxy.yml`` contains an empty ``version`` field (https://github.com/ansible/ansible/pull/83831). +- ssh - Fix bug when attempting to fetch a file path with characters that should be quoted when using the ``piped`` transfer method + v2.17.3 ======= diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/changelogs/changelog.yaml new/ansible_core-2.17.4/changelogs/changelog.yaml --- old/ansible_core-2.17.3/changelogs/changelog.yaml 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/changelogs/changelog.yaml 2024-09-09 21:26:24.000000000 +0200 @@ -825,3 +825,63 @@ - ansible-test-vyos.yml - mc_fix.yml release_date: '2024-08-05' + 2.17.4: + changes: + release_summary: '| Release Date: 2024-09-09 + + | `Porting Guide <https://docs.ansible.com/ansible-core/2.17/porting_guides/porting_guide_core_2.17.html>`__ + + ' + codename: Gallows Pole + fragments: + - 2.17.4_summary.yaml + release_date: '2024-09-09' + 2.17.4rc1: + changes: + bugfixes: + - Fix ``SemanticVersion.parse()`` to store the version string so that ``__repr__`` + reports it instead of ``None`` (https://github.com/ansible/ansible/pull/83831). + - Fix an issue where registered variable was not available for templating in + ``loop_control.label`` on skipped looped tasks (https://github.com/ansible/ansible/issues/83619) + - Fix for ``meta`` tasks breaking host/fork affinity with ``host_pinned`` strategy + (https://github.com/ansible/ansible/issues/83294) + - Fix using the current task's directory for looking up relative paths within + roles (https://github.com/ansible/ansible/issues/82695). + - atomic_move - fix using the setgid bit on the parent directory when creating + files (https://github.com/ansible/ansible/issues/46742, https://github.com/ansible/ansible/issues/67177). + - connection plugins using the 'extras' option feature would need variables + to match the plugin's loaded name, sometimes requiring fqcn, which is not + the same as the documented/declared/expected variables. Now we fall back to + the 'basename' of the fqcn, but plugin authors can still set the expected + value directly. + - csvfile lookup - give an error when no search term is provided using modern + config syntax (https://github.com/ansible/ansible/issues/83689). + - include_tasks - Display location when attempting to load a task list where + ``include_*`` did not specify any value - https://github.com/ansible/ansible/issues/83874 + - powershell - Improve CLIXML decoding to decode all control characters and + unicode characters that are encoded as surrogate pairs. + - psrp - Fix bug when attempting to fetch a file path that contains special + glob characters like ``[]`` + - runtime-metadata sanity test - do not crash on deprecations if ``galaxy.yml`` + contains an empty ``version`` field (https://github.com/ansible/ansible/pull/83831). + - ssh - Fix bug when attempting to fetch a file path with characters that should + be quoted when using the ``piped`` transfer method + release_summary: '| Release Date: 2024-09-03 + + | `Porting Guide <https://docs.ansible.com/ansible-core/2.17/porting_guides/porting_guide_core_2.17.html>`__ + + ' + codename: Gallows Pole + fragments: + - 2.17.4rc1_summary.yaml + - 46742-atomic_move-fix-setgid.yml + - 83294-meta-host_pinned-affinity.yml + - 83619-loop-label-register.yml + - 83831-runtime-metadata-fix.yml + - 83874-include-parse-error-location.yml + - dwim_is_role_fix_task_relative.yml + - extras_fix.yml + - fetch-filename.yml + - fix-inconsistent-csvfile-missing-search-error.yml + - powershell-clixml.yml + release_date: '2024-09-03' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/lib/ansible/config/base.yml new/ansible_core-2.17.4/lib/ansible/config/base.yml --- old/ansible_core-2.17.3/lib/ansible/config/base.yml 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/lib/ansible/config/base.yml 2024-09-09 21:26:24.000000000 +0200 @@ -948,7 +948,7 @@ - This was introduced as a way to reset role variables to default values if a role is used more than once in a playbook. - Starting in version '2.17' M(ansible.builtin.include_roles) and M(ansible.builtin.import_roles) can - indivudually override this via the C(public) parameter. + individually override this via the C(public) parameter. - Included roles only make their variables public at execution, unlike imported roles which happen at playbook compile time. env: [{name: ANSIBLE_PRIVATE_ROLE_VARS}] ini: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/lib/ansible/executor/task_executor.py new/ansible_core-2.17.4/lib/ansible/executor/task_executor.py --- old/ansible_core-2.17.3/lib/ansible/executor/task_executor.py 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/lib/ansible/executor/task_executor.py 2024-09-09 21:26:24.000000000 +0200 @@ -31,7 +31,7 @@ from ansible.utils.unsafe_proxy import to_unsafe_text, wrap_var from ansible.vars.clean import namespace_facts, clean_facts from ansible.utils.display import Display -from ansible.utils.vars import combine_vars, isidentifier +from ansible.utils.vars import combine_vars display = Display() @@ -332,6 +332,13 @@ (self._task, tmp_task) = (tmp_task, self._task) (self._play_context, tmp_play_context) = (tmp_play_context, self._play_context) res = self._execute(variables=task_vars) + + if self._task.register: + # Ensure per loop iteration results are registered in case `_execute()` + # returns early (when conditional, failure, ...). + # This is needed in case the registered variable is used in the loop label template. + task_vars[self._task.register] = res + task_fields = self._task.dump_attrs() (self._task, tmp_task) = (tmp_task, self._task) (self._play_context, tmp_play_context) = (tmp_play_context, self._play_context) @@ -657,9 +664,6 @@ # update the local copy of vars with the registered value, if specified, # or any facts which may have been generated by the module execution if self._task.register: - if not isidentifier(self._task.register): - raise AnsibleError("Invalid variable name in 'register' specified: '%s'" % self._task.register) - vars_copy[self._task.register] = result if self._task.async_val > 0: @@ -1048,7 +1052,7 @@ # add extras if plugin supports them if getattr(self._connection, 'allow_extras', False): for k in variables: - if k.startswith('ansible_%s_' % self._connection._load_name) and k not in options: + if k.startswith('ansible_%s_' % self._connection.extras_prefix) and k not in options: options['_extras'][k] = templar.template(variables[k]) task_keys = self._task.dump_attrs() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/lib/ansible/module_utils/ansible_release.py new/ansible_core-2.17.4/lib/ansible/module_utils/ansible_release.py --- old/ansible_core-2.17.3/lib/ansible/module_utils/ansible_release.py 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/lib/ansible/module_utils/ansible_release.py 2024-09-09 21:26:24.000000000 +0200 @@ -17,6 +17,6 @@ from __future__ import annotations -__version__ = '2.17.3' +__version__ = '2.17.4' __author__ = 'Ansible, Inc.' __codename__ = "Gallows Pole" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/lib/ansible/module_utils/basic.py new/ansible_core-2.17.4/lib/ansible/module_utils/basic.py --- old/ansible_core-2.17.3/lib/ansible/module_utils/basic.py 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/lib/ansible/module_utils/basic.py 2024-09-09 21:26:24.000000000 +0200 @@ -1686,8 +1686,12 @@ umask = os.umask(0) os.umask(umask) os.chmod(b_dest, S_IRWU_RWG_RWO & ~umask) + dest_dir_stat = os.stat(os.path.dirname(b_dest)) try: - os.chown(b_dest, os.geteuid(), os.getegid()) + if dest_dir_stat.st_mode & stat.S_ISGID: + os.chown(b_dest, os.geteuid(), dest_dir_stat.st_gid) + else: + os.chown(b_dest, os.geteuid(), os.getegid()) except OSError: # We're okay with trying our best here. If the user is not # root (or old Unices) they won't be able to chown. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/lib/ansible/parsing/dataloader.py new/ansible_core-2.17.4/lib/ansible/parsing/dataloader.py --- old/ansible_core-2.17.3/lib/ansible/parsing/dataloader.py 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/lib/ansible/parsing/dataloader.py 2024-09-09 21:26:24.000000000 +0200 @@ -329,11 +329,10 @@ if (is_role or self._is_role(path)) and b_pb_base_dir.endswith(b'/tasks'): search.append(os.path.join(os.path.dirname(b_pb_base_dir), b_dirname, b_source)) search.append(os.path.join(b_pb_base_dir, b_source)) - else: - # don't add dirname if user already is using it in source - if b_source.split(b'/')[0] != dirname: - search.append(os.path.join(b_upath, b_dirname, b_source)) - search.append(os.path.join(b_upath, b_source)) + # don't add dirname if user already is using it in source + if b_source.split(b'/')[0] != dirname: + search.append(os.path.join(b_upath, b_dirname, b_source)) + search.append(os.path.join(b_upath, b_source)) # always append basedir as last resort # don't add dirname if user already is using it in source diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/lib/ansible/playbook/task.py new/ansible_core-2.17.4/lib/ansible/playbook/task.py --- old/ansible_core-2.17.3/lib/ansible/playbook/task.py 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/lib/ansible/playbook/task.py 2024-09-09 21:26:24.000000000 +0200 @@ -37,6 +37,7 @@ from ansible.utils.collection_loader import AnsibleCollectionConfig from ansible.utils.display import Display from ansible.utils.sentinel import Sentinel +from ansible.utils.vars import isidentifier __all__ = ['Task'] @@ -274,6 +275,10 @@ if not isinstance(value, list): setattr(self, name, [value]) + def _validate_register(self, attr, name, value): + if value is not None and not isidentifier(value): + raise AnsibleParserError(f"Invalid variable name in 'register' specified: '{value}'") + def post_validate(self, templar): ''' Override of base class post_validate, to also do final validation on diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/lib/ansible/playbook/task_include.py new/ansible_core-2.17.4/lib/ansible/playbook/task_include.py --- old/ansible_core-2.17.3/lib/ansible/playbook/task_include.py 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/lib/ansible/playbook/task_include.py 2024-09-09 21:26:24.000000000 +0200 @@ -74,7 +74,7 @@ if not task.args.get('_raw_params'): task.args['_raw_params'] = task.args.pop('file', None) if not task.args['_raw_params']: - raise AnsibleParserError('No file specified for %s' % task.action) + raise AnsibleParserError('No file specified for %s' % task.action, obj=data) apply_attrs = task.args.get('apply', {}) if apply_attrs and task.action not in C._ACTION_INCLUDE_TASKS: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/lib/ansible/plugins/__init__.py new/ansible_core-2.17.4/lib/ansible/plugins/__init__.py --- old/ansible_core-2.17.3/lib/ansible/plugins/__init__.py 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/lib/ansible/plugins/__init__.py 2024-09-09 21:26:24.000000000 +0200 @@ -50,16 +50,23 @@ class AnsiblePlugin(ABC): - # allow extra passthrough parameters - allow_extras = False - # Set by plugin loader _load_name: str + # allow extra passthrough parameters + allow_extras: bool = False + _extras_prefix: str | None = None + def __init__(self): self._options = {} self._defs = None + @property + def extras_prefix(self): + if not self._extras_prefix: + self._extras_prefix = self._load_name.split('.')[-1] + return self._extras_prefix + def matches_name(self, possible_names): possible_fqcns = set() for name in possible_names: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/lib/ansible/plugins/connection/psrp.py new/ansible_core-2.17.4/lib/ansible/plugins/connection/psrp.py --- old/ansible_core-2.17.3/lib/ansible/plugins/connection/psrp.py 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/lib/ansible/plugins/connection/psrp.py 2024-09-09 21:26:24.000000000 +0200 @@ -632,39 +632,41 @@ buffer_size = max_b64_size - (max_b64_size % 1024) # setup the file stream with read only mode - setup_script = '''$ErrorActionPreference = "Stop" -$path = '%s' + setup_script = '''param([string]$Path) +$ErrorActionPreference = "Stop" -if (Test-Path -Path $path -PathType Leaf) { +if (Test-Path -LiteralPath $path -PathType Leaf) { $fs = New-Object -TypeName System.IO.FileStream -ArgumentList @( $path, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::Read ) - $buffer_size = %d } elseif (Test-Path -Path $path -PathType Container) { Write-Output -InputObject "[DIR]" } else { Write-Error -Message "$path does not exist" $host.SetShouldExit(1) -}''' % (self._shell._escape(in_path), buffer_size) +}''' # read the file stream at the offset and return the b64 string - read_script = '''$ErrorActionPreference = "Stop" -$fs.Seek(%d, [System.IO.SeekOrigin]::Begin) > $null -$buffer = New-Object -TypeName byte[] -ArgumentList $buffer_size -$bytes_read = $fs.Read($buffer, 0, $buffer_size) - -if ($bytes_read -gt 0) { - $bytes = $buffer[0..($bytes_read - 1)] - Write-Output -InputObject ([System.Convert]::ToBase64String($bytes)) + read_script = '''param([int64]$Offset, [int]$BufferSize) +$ErrorActionPreference = "Stop" +$fs.Seek($Offset, [System.IO.SeekOrigin]::Begin) > $null +$buffer = New-Object -TypeName byte[] -ArgumentList $BufferSize +$read = $fs.Read($buffer, 0, $buffer.Length) + +if ($read -gt 0) { + [System.Convert]::ToBase64String($buffer, 0, $read) }''' # need to run the setup script outside of the local scope so the # file stream stays active between fetch operations - rc, stdout, stderr = self._exec_psrp_script(setup_script, - use_local_scope=False) + rc, stdout, stderr = self._exec_psrp_script( + setup_script, + use_local_scope=False, + arguments=[in_path], + ) if rc != 0: raise AnsibleError("failed to setup file stream for fetch '%s': %s" % (out_path, to_native(stderr))) @@ -679,7 +681,10 @@ while True: display.vvvvv("PSRP FETCH %s to %s (offset=%d" % (in_path, out_path, offset), host=self._psrp_host) - rc, stdout, stderr = self._exec_psrp_script(read_script % offset) + rc, stdout, stderr = self._exec_psrp_script( + read_script, + arguments=[offset, buffer_size], + ) if rc != 0: raise AnsibleError("failed to transfer file to '%s': %s" % (out_path, to_native(stderr))) @@ -813,7 +818,7 @@ script: str, input_data: bytes | str | t.Iterable | None = None, use_local_scope: bool = True, - arguments: t.Iterable[str] | None = None, + arguments: t.Iterable[t.Any] | None = None, ) -> tuple[int, bytes, bytes]: # Check if there's a command on the current pipeline that still needs to be closed. if self._last_pipeline: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/lib/ansible/plugins/connection/ssh.py new/ansible_core-2.17.4/lib/ansible/plugins/connection/ssh.py --- old/ansible_core-2.17.3/lib/ansible/plugins/connection/ssh.py 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/lib/ansible/plugins/connection/ssh.py 2024-09-09 21:26:24.000000000 +0200 @@ -1250,7 +1250,7 @@ if sftp_action == 'get': # we pass sudoable=False to disable pty allocation, which # would end up mixing stdout/stderr and screwing with newlines - (returncode, stdout, stderr) = self.exec_command('dd if=%s bs=%s' % (in_path, BUFSIZE), sudoable=False) + (returncode, stdout, stderr) = self.exec_command('dd if=%s bs=%s' % (self._shell.quote(in_path), BUFSIZE), sudoable=False) with open(to_bytes(out_path, errors='surrogate_or_strict'), 'wb+') as out_file: out_file.write(stdout) else: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/lib/ansible/plugins/lookup/csvfile.py new/ansible_core-2.17.4/lib/ansible/plugins/lookup/csvfile.py --- old/ansible_core-2.17.3/lib/ansible/plugins/lookup/csvfile.py 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/lib/ansible/plugins/lookup/csvfile.py 2024-09-09 21:26:24.000000000 +0200 @@ -12,6 +12,7 @@ - The csvfile lookup reads the contents of a file in CSV (comma-separated value) format. The lookup looks for the row where the first column matches keyname (which can be multiple words) and returns the value in the O(col) column (default 1, which indexed from 0 means the second column in the file). + - At least one keyname is required, provided as a positional argument(s) to the lookup. options: col: description: column to return (0 indexed). @@ -63,6 +64,22 @@ vars: csvline: "{{ lookup('ansible.builtin.csvfile', bgp_neighbor_ip, file='bgp_neighbors.csv', delimiter=',') }}" delegate_to: localhost + +# Contents of debug.csv +# test1 ret1.1 ret2.1 +# test2 ret1.2 ret2.2 +# test3 ret1.3 ret2.3 + +- name: "Lookup multiple keynames in the first column (index 0), returning the values from the second column (index 1)" + debug: + msg: "{{ lookup('csvfile', 'test1', 'test2', file='debug.csv', delimiter=' ') }}" + +- name: Lookup multiple keynames using old style syntax + debug: + msg: "{{ lookup('csvfile', term1, term2) }}" + vars: + term1: "test1 file=debug.csv delimiter=' '" + term2: "test2 file=debug.csv delimiter=' '" """ RETURN = """ @@ -150,6 +167,9 @@ # populate options paramvals = self.get_options() + if not terms: + raise AnsibleError('Search key is required but was not found') + for term in terms: kv = parse_kv(term) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/lib/ansible/plugins/shell/powershell.py new/ansible_core-2.17.4/lib/ansible/plugins/shell/powershell.py --- old/ansible_core-2.17.3/lib/ansible/plugins/shell/powershell.py 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/lib/ansible/plugins/shell/powershell.py 2024-09-09 21:26:24.000000000 +0200 @@ -25,35 +25,70 @@ from ansible.module_utils.common.text.converters import to_bytes, to_text from ansible.plugins.shell import ShellBase +# This is weird, we are matching on byte sequences that match the utf-16-be +# matches for '_x(a-fA-F0-9){4}_'. The \x00 and {8} will match the hex sequence +# when it is encoded as utf-16-be. +_STRING_DESERIAL_FIND = re.compile(rb"\x00_\x00x([\x00(a-fA-F0-9)]{8})\x00_") _common_args = ['PowerShell', '-NoProfile', '-NonInteractive', '-ExecutionPolicy', 'Unrestricted'] -def _parse_clixml(data, stream="Error"): +def _parse_clixml(data: bytes, stream: str = "Error") -> bytes: """ Takes a byte string like '#< CLIXML\r\n<Objs...' and extracts the stream message encoded in the XML data. CLIXML is used by PowerShell to encode multiple objects in stderr. """ - lines = [] + lines: list[str] = [] + + # A serialized string will serialize control chars and surrogate pairs as + # _xDDDD_ values where DDDD is the hex representation of a big endian + # UTF-16 code unit. As a surrogate pair uses 2 UTF-16 code units, we need + # to operate our text replacement on the utf-16-be byte encoding of the raw + # text. This allows us to replace the _xDDDD_ values with the actual byte + # values and then decode that back to a string from the utf-16-be bytes. + def rplcr(matchobj: re.Match) -> bytes: + match_hex = matchobj.group(1) + hex_string = match_hex.decode("utf-16-be") + return base64.b16decode(hex_string.upper()) # There are some scenarios where the stderr contains a nested CLIXML element like # '<# CLIXML\r\n<# CLIXML\r\n<Objs>...</Objs><Objs>...</Objs>'. # Parse each individual <Objs> element and add the error strings to our stderr list. # https://github.com/ansible/ansible/issues/69550 while data: - end_idx = data.find(b"</Objs>") + 7 - current_element = data[data.find(b"<Objs "):end_idx] + start_idx = data.find(b"<Objs ") + end_idx = data.find(b"</Objs>") + if start_idx == -1 or end_idx == -1: + break + + end_idx += 7 + current_element = data[start_idx:end_idx] data = data[end_idx:] clixml = ET.fromstring(current_element) namespace_match = re.match(r'{(.*)}', clixml.tag) - namespace = "{%s}" % namespace_match.group(1) if namespace_match else "" + namespace = f"{{{namespace_match.group(1)}}}" if namespace_match else "" + + entries = clixml.findall("./%sS" % namespace) + if not entries: + continue + + # If this is a new CLIXML element, add a newline to separate the messages. + if lines: + lines.append("\r\n") + + for string_entry in entries: + actual_stream = string_entry.attrib.get('S', None) + if actual_stream != stream: + continue + + b_line = (string_entry.text or "").encode("utf-16-be") + b_escaped = re.sub(_STRING_DESERIAL_FIND, rplcr, b_line) - strings = clixml.findall("./%sS" % namespace) - lines.extend([e.text.replace('_x000D__x000A_', '') for e in strings if e.attrib.get('S') == stream]) + lines.append(b_escaped.decode("utf-16-be", errors="surrogatepass")) - return to_bytes('\r\n'.join(lines)) + return to_bytes(''.join(lines), errors="surrogatepass") class ShellModule(ShellBase): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/lib/ansible/plugins/strategy/__init__.py new/ansible_core-2.17.4/lib/ansible/plugins/strategy/__init__.py --- old/ansible_core-2.17.3/lib/ansible/plugins/strategy/__init__.py 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/lib/ansible/plugins/strategy/__init__.py 2024-09-09 21:26:24.000000000 +0200 @@ -54,7 +54,7 @@ from ansible.utils.fqcn import add_internal_fqcns from ansible.utils.unsafe_proxy import wrap_var from ansible.utils.sentinel import Sentinel -from ansible.utils.vars import combine_vars, isidentifier +from ansible.utils.vars import combine_vars from ansible.vars.clean import strip_internal_keys, module_response_deepcopy display = Display() @@ -766,10 +766,6 @@ # register final results if original_task.register: - - if not isidentifier(original_task.register): - raise AnsibleError("Invalid variable name in 'register' specified: '%s'" % original_task.register) - host_list = self.get_task_hosts(iterator, original_host, original_task) clean_copy = strip_internal_keys(module_response_deepcopy(task_result._result)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/lib/ansible/plugins/strategy/free.py new/ansible_core-2.17.4/lib/ansible/plugins/strategy/free.py --- old/ansible_core-2.17.3/lib/ansible/plugins/strategy/free.py 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/lib/ansible/plugins/strategy/free.py 2024-09-09 21:26:24.000000000 +0200 @@ -95,6 +95,7 @@ # try and find an unblocked host with a task to run host_results = [] + meta_task_dummy_results_count = 0 while True: host = hosts_left[last_host] display.debug("next free host: %s" % host) @@ -181,6 +182,9 @@ continue if task.action in C._ACTION_META: + if self._host_pinned: + meta_task_dummy_results_count += 1 + workers_free -= 1 self._execute_meta(task, play_context, iterator, target_host=host) self._blocked_hosts[host_name] = False else: @@ -220,7 +224,7 @@ host_results.extend(results) # each result is counted as a worker being free again - workers_free += len(results) + workers_free += len(results) + meta_task_dummy_results_count self.update_active_connections(results) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/lib/ansible/release.py new/ansible_core-2.17.4/lib/ansible/release.py --- old/ansible_core-2.17.3/lib/ansible/release.py 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/lib/ansible/release.py 2024-09-09 21:26:24.000000000 +0200 @@ -17,6 +17,6 @@ from __future__ import annotations -__version__ = '2.17.3' +__version__ = '2.17.4' __author__ = 'Ansible, Inc.' __codename__ = "Gallows Pole" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/lib/ansible/utils/version.py new/ansible_core-2.17.4/lib/ansible/utils/version.py --- old/ansible_core-2.17.3/lib/ansible/utils/version.py 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/lib/ansible/utils/version.py 2024-09-09 21:26:24.000000000 +0200 @@ -190,6 +190,7 @@ raise ValueError("invalid semantic version '%s'" % vstring) (major, minor, patch, prerelease, buildmetadata) = match.group(1, 2, 3, 4, 5) + self.vstring = vstring self.major = int(major) self.minor = int(minor) self.patch = int(patch) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/lib/ansible_core.egg-info/PKG-INFO new/ansible_core-2.17.4/lib/ansible_core.egg-info/PKG-INFO --- old/ansible_core-2.17.3/lib/ansible_core.egg-info/PKG-INFO 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/lib/ansible_core.egg-info/PKG-INFO 2024-09-09 21:26:24.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: ansible-core -Version: 2.17.3 +Version: 2.17.4 Summary: Radically simple IT automation Home-page: https://ansible.com/ Author: Ansible, Inc. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/lib/ansible_core.egg-info/SOURCES.txt new/ansible_core-2.17.4/lib/ansible_core.egg-info/SOURCES.txt --- old/ansible_core-2.17.3/lib/ansible_core.egg-info/SOURCES.txt 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/lib/ansible_core.egg-info/SOURCES.txt 2024-09-09 21:26:24.000000000 +0200 @@ -1060,6 +1060,14 @@ test/integration/targets/ansible-test-sanity-replace-urlopen/runme.sh test/integration/targets/ansible-test-sanity-replace-urlopen/ansible_collections/ns/col/do-not-check-me.py test/integration/targets/ansible-test-sanity-replace-urlopen/ansible_collections/ns/col/plugins/modules/check-me.py +test/integration/targets/ansible-test-sanity-runtime-metadata/aliases +test/integration/targets/ansible-test-sanity-runtime-metadata/expected-no_version.txt +test/integration/targets/ansible-test-sanity-runtime-metadata/expected-version.txt +test/integration/targets/ansible-test-sanity-runtime-metadata/runme.sh +test/integration/targets/ansible-test-sanity-runtime-metadata/ansible_collections/ns/no_version/galaxy.yml +test/integration/targets/ansible-test-sanity-runtime-metadata/ansible_collections/ns/no_version/meta/runtime.yml +test/integration/targets/ansible-test-sanity-runtime-metadata/ansible_collections/ns/version/galaxy.yml +test/integration/targets/ansible-test-sanity-runtime-metadata/ansible_collections/ns/version/meta/runtime.yml test/integration/targets/ansible-test-sanity-shebang/aliases test/integration/targets/ansible-test-sanity-shebang/expected.txt test/integration/targets/ansible-test-sanity-shebang/runme.sh @@ -1740,6 +1748,7 @@ test/integration/targets/copy/tasks/main.yml test/integration/targets/copy/tasks/no_log.yml test/integration/targets/copy/tasks/selinux.yml +test/integration/targets/copy/tasks/setgid.yml test/integration/targets/copy/tasks/src_file_dest_file_in_non_existent_dir.yml test/integration/targets/copy/tasks/src_file_dest_file_in_non_existent_dir_remote_src.yml test/integration/targets/copy/tasks/src_remote_file_is_not_file.yml @@ -2209,6 +2218,7 @@ test/integration/targets/include_import/test_loop_var_bleed.yaml test/integration/targets/include_import/test_nested_tasks.yml test/integration/targets/include_import/test_nested_tasks_fqcn.yml +test/integration/targets/include_import/test_null_include_filename.yml test/integration/targets/include_import/test_role_recursion.yml test/integration/targets/include_import/test_role_recursion_fqcn.yml test/integration/targets/include_import/apply/import_apply.yml @@ -2233,6 +2243,7 @@ test/integration/targets/include_import/include_role_omit/playbook.yml test/integration/targets/include_import/include_role_omit/roles/foo/tasks/main.yml test/integration/targets/include_import/nestedtasks/nested/nested.yml +test/integration/targets/include_import/null_filename/tasks.yml test/integration/targets/include_import/parent_templating/playbook.yml test/integration/targets/include_import/parent_templating/roles/test/tasks/localhost.yml test/integration/targets/include_import/parent_templating/roles/test/tasks/main.yml @@ -2617,6 +2628,9 @@ test/integration/targets/lookup_first_found/files/bar1 test/integration/targets/lookup_first_found/files/foo1 test/integration/targets/lookup_first_found/files/vars file spaces.yml +test/integration/targets/lookup_first_found/roles/a/tasks/main.yml +test/integration/targets/lookup_first_found/roles/a/tasks/subdir/main.yml +test/integration/targets/lookup_first_found/roles/a/tasks/subdir/relative test/integration/targets/lookup_first_found/tasks/main.yml test/integration/targets/lookup_first_found/vars/ishouldnotbefound.yml test/integration/targets/lookup_first_found/vars/itworks.yml @@ -3451,6 +3465,11 @@ test/integration/targets/strategy_free/last_include_tasks.yml test/integration/targets/strategy_free/runme.sh test/integration/targets/strategy_free/test_last_include_in_always.yml +test/integration/targets/strategy_host_pinned/aliases +test/integration/targets/strategy_host_pinned/hosts +test/integration/targets/strategy_host_pinned/playbook.yml +test/integration/targets/strategy_host_pinned/runme.sh +test/integration/targets/strategy_host_pinned/callback_plugins/callback_host_count.py test/integration/targets/strategy_linear/aliases test/integration/targets/strategy_linear/inventory test/integration/targets/strategy_linear/runme.sh diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/packaging/release.py new/ansible_core-2.17.4/packaging/release.py --- old/ansible_core-2.17.3/packaging/release.py 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/packaging/release.py 2024-09-09 21:26:24.000000000 +0200 @@ -369,6 +369,7 @@ ANSIBLE_BIN_DIR = CHECKOUT_DIR / "bin" ANSIBLE_RELEASE_FILE = ANSIBLE_DIR / "release.py" ANSIBLE_REQUIREMENTS_FILE = CHECKOUT_DIR / "requirements.txt" +ANSIBLE_PYPROJECT_TOML_FILE = CHECKOUT_DIR / "pyproject.toml" DIST_DIR = CHECKOUT_DIR / "dist" VENV_DIR = DIST_DIR / ".venv" / "release" @@ -708,6 +709,35 @@ return env +def get_pypi_project(repository: str, project: str, version: Version | None = None) -> dict[str, t.Any]: + """Return the project JSON from PyPI for the specified repository, project and version (optional).""" + endpoint = PYPI_ENDPOINTS[repository] + + if version: + url = f"{endpoint}/{project}/{version}/json" + else: + url = f"{endpoint}/{project}/json" + + opener = urllib.request.build_opener() + response: http.client.HTTPResponse + + try: + with opener.open(url) as response: + data = json.load(response) + except urllib.error.HTTPError as ex: + if version: + target = f'{project!r} version {version}' + else: + target = f'{project!r}' + + if ex.status == http.HTTPStatus.NOT_FOUND: + raise ApplicationError(f"Could not find {target} on PyPI.") from None + + raise RuntimeError(f"Failed to get {target} from PyPI.") from ex + + return data + + def get_ansible_version(version: str | None = None, /, commit: str | None = None, mode: VersionMode = VersionMode.DEFAULT) -> Version: """Parse and return the current ansible-core version, the provided version or the version from the provided commit.""" if version and commit: @@ -802,6 +832,38 @@ ANSIBLE_RELEASE_FILE.write_text(updated) +def get_latest_setuptools_version() -> Version: + """Return the latest setuptools version found on PyPI.""" + data = get_pypi_project('pypi', 'setuptools') + version = Version(data['info']['version']) + + return version + + +def set_setuptools_upper_bound(requested_version: Version) -> None: + """Set the upper bound on setuptools in pyproject.toml.""" + current = ANSIBLE_PYPROJECT_TOML_FILE.read_text() + pattern = re.compile(r'^(?P<begin>requires = \["setuptools >= )(?P<lower>[^,]+)(?P<middle>, <= )(?P<upper>[^"]+)(?P<end>".*)$', re.MULTILINE) + match = pattern.search(current) + + if not match: + raise ApplicationError(f"Unable to find the 'requires' entry in: {ANSIBLE_PYPROJECT_TOML_FILE.relative_to(CHECKOUT_DIR)}") + + current_version = Version(match.group('upper')) + + if requested_version == current_version: + return + + display.show(f"Updating setuptools upper bound from {current_version} to {requested_version} ...") + + updated = pattern.sub(fr'\g<begin>\g<lower>\g<middle>{requested_version}\g<end>', current) + + if current == updated: + raise RuntimeError("Failed to set the setuptools upper bound.") + + ANSIBLE_PYPROJECT_TOML_FILE.write_text(updated) + + def create_reproducible_sdist(original_path: pathlib.Path, output_path: pathlib.Path, mtime: int) -> None: """Read the specified sdist and write out a new copy with uniform file metadata at the specified location.""" with tarfile.open(original_path) as original_archive: @@ -878,21 +940,7 @@ @functools.cache def get_release_artifact_details(repository: str, version: Version, validate: bool) -> list[ReleaseArtifact]: """Return information about the release artifacts hosted on PyPI.""" - endpoint = PYPI_ENDPOINTS[repository] - url = f"{endpoint}/ansible-core/{version}/json" - - opener = urllib.request.build_opener() - response: http.client.HTTPResponse - - try: - with opener.open(url) as response: - data = json.load(response) - except urllib.error.HTTPError as ex: - if ex.status == http.HTTPStatus.NOT_FOUND: - raise ApplicationError(f"Version {version} not found on PyPI.") from None - - raise RuntimeError(f"Failed to get {version} from PyPI: {ex}") from ex - + data = get_pypi_project(repository, 'ansible-core', version) artifacts = [describe_release_artifact(version, item, validate) for item in data["urls"]] expected_artifact_types = {"bdist_wheel", "sdist"} @@ -1138,6 +1186,7 @@ mailto=dict(name="--mailto", action="store_true", help="write announcement to mailto link instead of console"), validate=dict(name="--no-validate", action="store_false", help="disable validation of PyPI artifacts against local ones"), prompt=dict(name="--no-prompt", action="store_false", help="disable interactive prompt before publishing with twine"), + setuptools=dict(name='--no-setuptools', action="store_false", help="disable updating setuptools upper bound"), allow_tag=dict(action="store_true", help="allow an existing release tag (for testing)"), allow_stale=dict(action="store_true", help="allow a stale checkout (for testing)"), allow_dirty=dict(action="store_true", help="allow untracked files and files with changes (for testing)"), @@ -1194,10 +1243,11 @@ # noinspection PyUnusedLocal @command -def prepare(final: bool = False, pre: str | None = None, version: str | None = None) -> None: +def prepare(final: bool = False, pre: str | None = None, version: str | None = None, setuptools: bool | None = None) -> None: """Prepare a release.""" command.run( update_version, + update_setuptools, check_state, generate_summary, generate_changelog, @@ -1219,6 +1269,16 @@ @command +def update_setuptools(setuptools: bool) -> None: + """Update the setuptools upper bound in pyproject.toml.""" + if not setuptools: + return + + requested_version = get_latest_setuptools_version() + set_setuptools_upper_bound(requested_version) + + +@command def generate_summary() -> None: """Generate a summary changelog fragment for this release.""" version = get_ansible_version() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/pyproject.toml new/ansible_core-2.17.4/pyproject.toml --- old/ansible_core-2.17.3/pyproject.toml 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/pyproject.toml 2024-09-09 21:26:24.000000000 +0200 @@ -1,3 +1,3 @@ [build-system] -requires = ["setuptools >= 66.1.0"] # minimum setuptools version supporting Python 3.12 +requires = ["setuptools >= 66.1.0, <= 72.1.0"] # lower bound to support controller Python versions, upper bound for latest version tested at release build-backend = "setuptools.build_meta" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/test/integration/targets/ansible-test-sanity-runtime-metadata/aliases new/ansible_core-2.17.4/test/integration/targets/ansible-test-sanity-runtime-metadata/aliases --- old/ansible_core-2.17.3/test/integration/targets/ansible-test-sanity-runtime-metadata/aliases 1970-01-01 01:00:00.000000000 +0100 +++ new/ansible_core-2.17.4/test/integration/targets/ansible-test-sanity-runtime-metadata/aliases 2024-09-09 21:26:24.000000000 +0200 @@ -0,0 +1,4 @@ +shippable/posix/group3 # runs in the distro test containers +shippable/generic/group1 # runs in the default test container +context/controller +needs/target/collection diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/test/integration/targets/ansible-test-sanity-runtime-metadata/ansible_collections/ns/no_version/galaxy.yml new/ansible_core-2.17.4/test/integration/targets/ansible-test-sanity-runtime-metadata/ansible_collections/ns/no_version/galaxy.yml --- old/ansible_core-2.17.3/test/integration/targets/ansible-test-sanity-runtime-metadata/ansible_collections/ns/no_version/galaxy.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/ansible_core-2.17.4/test/integration/targets/ansible-test-sanity-runtime-metadata/ansible_collections/ns/no_version/galaxy.yml 2024-09-09 21:26:24.000000000 +0200 @@ -0,0 +1,5 @@ +namespace: ns +name: no_version +version: null +authors: + - Ansible diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/test/integration/targets/ansible-test-sanity-runtime-metadata/ansible_collections/ns/no_version/meta/runtime.yml new/ansible_core-2.17.4/test/integration/targets/ansible-test-sanity-runtime-metadata/ansible_collections/ns/no_version/meta/runtime.yml --- old/ansible_core-2.17.3/test/integration/targets/ansible-test-sanity-runtime-metadata/ansible_collections/ns/no_version/meta/runtime.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/ansible_core-2.17.4/test/integration/targets/ansible-test-sanity-runtime-metadata/ansible_collections/ns/no_version/meta/runtime.yml 2024-09-09 21:26:24.000000000 +0200 @@ -0,0 +1,11 @@ +extra_key: true +plugin_routing: + modules: + deprecated_module: + deprecation: + removal_version: 2.0.0 + warning_text: Will no longer be there. + tombstoned_module: + tombstone: + removal_version: 1.0.0 + warning_text: Is no longer there. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/test/integration/targets/ansible-test-sanity-runtime-metadata/ansible_collections/ns/version/galaxy.yml new/ansible_core-2.17.4/test/integration/targets/ansible-test-sanity-runtime-metadata/ansible_collections/ns/version/galaxy.yml --- old/ansible_core-2.17.3/test/integration/targets/ansible-test-sanity-runtime-metadata/ansible_collections/ns/version/galaxy.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/ansible_core-2.17.4/test/integration/targets/ansible-test-sanity-runtime-metadata/ansible_collections/ns/version/galaxy.yml 2024-09-09 21:26:24.000000000 +0200 @@ -0,0 +1,5 @@ +namespace: ns +name: version +version: 2.3.4 +authors: + - Ansible diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/test/integration/targets/ansible-test-sanity-runtime-metadata/ansible_collections/ns/version/meta/runtime.yml new/ansible_core-2.17.4/test/integration/targets/ansible-test-sanity-runtime-metadata/ansible_collections/ns/version/meta/runtime.yml --- old/ansible_core-2.17.3/test/integration/targets/ansible-test-sanity-runtime-metadata/ansible_collections/ns/version/meta/runtime.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/ansible_core-2.17.4/test/integration/targets/ansible-test-sanity-runtime-metadata/ansible_collections/ns/version/meta/runtime.yml 2024-09-09 21:26:24.000000000 +0200 @@ -0,0 +1,18 @@ +plugin_routing: + modules: + deprecated_module: + deprecation: + removal_version: 3.0.0 + warning_text: Will no longer be there. + tombstoned_module: + tombstone: + removal_version: 2.0.0 + warning_text: Is no longer there. + deprecated_module_wrong_version: + deprecation: + removal_version: 2.0.0 + warning_text: Will no longer be there. + tombstoned_module_wrong_version: + tombstone: + removal_version: 3.0.0 + warning_text: Is no longer there. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/test/integration/targets/ansible-test-sanity-runtime-metadata/expected-no_version.txt new/ansible_core-2.17.4/test/integration/targets/ansible-test-sanity-runtime-metadata/expected-no_version.txt --- old/ansible_core-2.17.3/test/integration/targets/ansible-test-sanity-runtime-metadata/expected-no_version.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/ansible_core-2.17.4/test/integration/targets/ansible-test-sanity-runtime-metadata/expected-no_version.txt 2024-09-09 21:26:24.000000000 +0200 @@ -0,0 +1 @@ +meta/runtime.yml:0:0: extra keys not allowed @ data['extra_key']. Got True diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/test/integration/targets/ansible-test-sanity-runtime-metadata/expected-version.txt new/ansible_core-2.17.4/test/integration/targets/ansible-test-sanity-runtime-metadata/expected-version.txt --- old/ansible_core-2.17.3/test/integration/targets/ansible-test-sanity-runtime-metadata/expected-version.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/ansible_core-2.17.4/test/integration/targets/ansible-test-sanity-runtime-metadata/expected-version.txt 2024-09-09 21:26:24.000000000 +0200 @@ -0,0 +1,2 @@ +meta/runtime.yml:0:0: The deprecation removal_version ('2.0.0') must be after the current version (SemanticVersion('2.3.4')) for dictionary value @ data['plugin_routing']['modules']['deprecated_module_wrong_version']['deprecation']['removal_version']. Got '2.0.0' +meta/runtime.yml:0:0: The tombstone removal_version ('3.0.0') must not be after the current version (SemanticVersion('2.3.4')) for dictionary value @ data['plugin_routing']['modules']['tombstoned_module_wrong_version']['tombstone']['removal_version']. Got '3.0.0' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/test/integration/targets/ansible-test-sanity-runtime-metadata/runme.sh new/ansible_core-2.17.4/test/integration/targets/ansible-test-sanity-runtime-metadata/runme.sh --- old/ansible_core-2.17.3/test/integration/targets/ansible-test-sanity-runtime-metadata/runme.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/ansible_core-2.17.4/test/integration/targets/ansible-test-sanity-runtime-metadata/runme.sh 2024-09-09 21:26:24.000000000 +0200 @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +COLLECTION_NAME=version source ../collection/setup.sh + +set -eux + +cd ../version +ansible-test sanity --test runtime-metadata --color --truncate 0 --failure-ok --lint "${@}" 1> actual-stdout.txt 2> actual-stderr.txt +diff -u "${TEST_DIR}/expected-version.txt" actual-stdout.txt +grep -F -f "${TEST_DIR}/expected-version.txt" actual-stderr.txt + +cd ../no_version +ansible-test sanity --test runtime-metadata --color --truncate 0 --failure-ok --lint "${@}" 1> actual-stdout.txt 2> actual-stderr.txt +diff -u "${TEST_DIR}/expected-no_version.txt" actual-stdout.txt +grep -F -f "${TEST_DIR}/expected-no_version.txt" actual-stderr.txt diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/test/integration/targets/ansible-vault/runme.sh new/ansible_core-2.17.4/test/integration/targets/ansible-vault/runme.sh --- old/ansible_core-2.17.3/test/integration/targets/ansible-vault/runme.sh 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/test/integration/targets/ansible-vault/runme.sh 2024-09-09 21:26:24.000000000 +0200 @@ -546,21 +546,22 @@ ansible-vault encrypt_string content ansible-vault encrypt_string content --encrypt-vault-id id3 -set +e - # Try to use a missing vault password file -ansible-vault encrypt_string content --encrypt-vault-id id1 2>&1 | tee out.txt -test $? -ne 0 -grep out.txt -e '[WARNING]: Error getting vault password file (id1)' -grep out.txt -e "ERROR! Did not find a match for --encrypt-vault-id=id2 in the known vault-ids ['id3']" +if ansible-vault encrypt_string content --encrypt-vault-id id1 > out.txt 2>&1; then + echo "command did not fail" + exit 1 +fi +grep out.txt -e '\[WARNING\]: Error getting vault password file (id1)' +grep out.txt -e "ERROR! Did not find a match for --encrypt-vault-id=id1 in the known vault-ids \['id3'\]" # Try to use an inaccessible vault password file -ansible-vault encrypt_string content --encrypt-vault-id id2 2>&1 | tee out.txt -test $? -ne 0 -grep out.txt -e "[WARNING]: Error in vault password file loading (id2)" -grep out.txt -e "ERROR! Did not find a match for --encrypt-vault-id=id2 in the known vault-ids ['id3']" +if ansible-vault encrypt_string content --encrypt-vault-id id2 > out.txt 2>&1; then + echo "command did not fail" + exit 1 +fi +grep out.txt -e "\[WARNING\]: Error in vault password file loading (id2)" +grep out.txt -e "ERROR! Did not find a match for --encrypt-vault-id=id2 in the known vault-ids \['id3'\]" -set -e unset ANSIBLE_VAULT_IDENTITY_LIST # 'real script' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/test/integration/targets/collection/setup.sh new/ansible_core-2.17.4/test/integration/targets/collection/setup.sh --- old/ansible_core-2.17.3/test/integration/targets/collection/setup.sh 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/test/integration/targets/collection/setup.sh 2024-09-09 21:26:24.000000000 +0200 @@ -24,6 +24,6 @@ trap 'rm -rf "${WORK_DIR}"' EXIT cp -a "${TEST_DIR}/ansible_collections" "${WORK_DIR}" -cd "${WORK_DIR}/ansible_collections/ns/col" +cd "${WORK_DIR}/ansible_collections/ns/${COLLECTION_NAME:-col}" "${TEST_DIR}/../collection/update-ignore.py" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/test/integration/targets/connection/test_connection.yml new/ansible_core-2.17.4/test/integration/targets/connection/test_connection.yml --- old/ansible_core-2.17.3/test/integration/targets/connection/test_connection.yml 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/test/integration/targets/connection/test_connection.yml 2024-09-09 21:26:24.000000000 +0200 @@ -3,6 +3,25 @@ serial: 1 tasks: + # SSH with scp has troubles with using complex filenames that require quoting + # or escaping. The more complex filename scenario is skipped in this mode. + # The default of sftp has no problems with these filenames. + - name: check if ssh with the scp file transfer is being tested + set_fact: + skip_complex_filename: >- + {{ + ansible_connection == "ssh" and + lookup("ansible.builtin.config", + "ssh_transfer_method", + plugin_name=ansible_connection, + plugin_type="connection", + ) == "scp" + }} + + - name: set test filename + set_fact: + test_filename: æ±è¯-{{ skip_complex_filename | ternary("file", "['foo bar']") }}.txt + ### raw with unicode arg and output - name: raw with unicode arg and output @@ -17,20 +36,20 @@ ### copy local file with unicode filename and content - name: create local file with unicode filename and content - local_action: lineinfile dest={{ local_tmp }}-æ±è¯/æ±è¯.txt create=true line=æ±è¯ + local_action: lineinfile dest={{ local_tmp }}-æ±è¯/{{ test_filename }} create=true line=æ±è¯ - name: remove remote file with unicode filename and content - action: "{{ action_prefix }}file path={{ remote_tmp }}-æ±è¯/æ±è¯.txt state=absent" + action: "{{ action_prefix }}file path={{ remote_tmp }}-æ±è¯/{{ test_filename }} state=absent" - name: create remote directory with unicode name action: "{{ action_prefix }}file path={{ remote_tmp }}-æ±è¯ state=directory" - name: copy local file with unicode filename and content - action: "{{ action_prefix }}copy src={{ local_tmp }}-æ±è¯/æ±è¯.txt dest={{ remote_tmp }}-æ±è¯/æ±è¯.txt" + action: "{{ action_prefix }}copy src={{ local_tmp }}-æ±è¯/{{ test_filename }} dest={{ remote_tmp }}-æ±è¯/{{ test_filename }}" ### fetch remote file with unicode filename and content - name: remove local file with unicode filename and content - local_action: file path={{ local_tmp }}-æ±è¯/æ±è¯.txt state=absent + local_action: file path={{ local_tmp }}-æ±è¯/{{ test_filename }} state=absent - name: fetch remote file with unicode filename and content - fetch: src={{ remote_tmp }}-æ±è¯/æ±è¯.txt dest={{ local_tmp }}-æ±è¯/æ±è¯.txt fail_on_missing=true validate_checksum=true flat=true + fetch: src={{ remote_tmp }}-æ±è¯/{{ test_filename }} dest={{ local_tmp }}-æ±è¯/{{ test_filename }} fail_on_missing=true validate_checksum=true flat=true ### remove local and remote temp files diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/test/integration/targets/connection_psrp/tests.yml new/ansible_core-2.17.4/test/integration/targets/connection_psrp/tests.yml --- old/ansible_core-2.17.3/test/integration/targets/connection_psrp/tests.yml 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/test/integration/targets/connection_psrp/tests.yml 2024-09-09 21:26:24.000000000 +0200 @@ -126,3 +126,16 @@ path: /tmp/empty.txt state: absent delegate_to: localhost + + - name: Test PSRP HTTP connection + win_ping: + vars: + ansible_port: 5985 + ansible_psrp_protocol: http + + - name: Test PSRP HTTPS connection + win_ping: + vars: + ansible_port: 5986 + ansible_psrp_protocol: https + ansible_psrp_cert_validation: ignore diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/test/integration/targets/connection_winrm/tests.yml new/ansible_core-2.17.4/test/integration/targets/connection_winrm/tests.yml --- old/ansible_core-2.17.3/test/integration/targets/connection_winrm/tests.yml 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/test/integration/targets/connection_winrm/tests.yml 2024-09-09 21:26:24.000000000 +0200 @@ -41,3 +41,26 @@ - assert: that: - timeout_cmd.msg == 'The win_shell action failed to execute in the expected time frame (5) and was terminated' + + - name: Test WinRM HTTP connection + win_ping: + vars: + ansible_port: 5985 + ansible_winrm_scheme: http + ansible_winrm_transport: ntlm # Verifies message encryption over HTTP + + - name: Test WinRM HTTPS connection + win_ping: + vars: + ansible_port: 5986 + ansible_winrm_scheme: https + ansible_winrm_server_cert_validation: ignore + + - name: emit raw CLIXML on stderr with special chars + raw: $host.UI.WriteErrorLine("Test ðµ _x005F_ _x005Z_.") + register: stderr_clixml + + - name: assert emit raw CLIXML on stderr with special chars + assert: + that: + - stderr_clixml.stderr_lines == ['Test ðµ _x005F_ _x005Z_.'] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/test/integration/targets/copy/defaults/main.yml new/ansible_core-2.17.4/test/integration/targets/copy/defaults/main.yml --- old/ansible_core-2.17.3/test/integration/targets/copy/defaults/main.yml 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/test/integration/targets/copy/defaults/main.yml 2024-09-09 21:26:24.000000000 +0200 @@ -1,2 +1,3 @@ --- remote_unprivileged_user: tmp_ansible_test_user +remote_unprivileged_user_group: test_ansible_test_group diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/test/integration/targets/copy/tasks/main.yml new/ansible_core-2.17.4/test/integration/targets/copy/tasks/main.yml --- old/ansible_core-2.17.3/test/integration/targets/copy/tasks/main.yml 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/test/integration/targets/copy/tasks/main.yml 2024-09-09 21:26:24.000000000 +0200 @@ -29,9 +29,15 @@ with_dict: "{{ symlinks }}" delegate_to: localhost + - name: Create group for remote unprivileged user + group: + name: '{{ remote_unprivileged_user_group }}' + register: group + - name: Create remote unprivileged remote user user: name: '{{ remote_unprivileged_user }}' + group: '{{ remote_unprivileged_user_group }}' register: user - name: Check sudoers dir @@ -78,6 +84,8 @@ - import_tasks: selinux.yml when: ansible_os_family == 'RedHat' and ansible_selinux.get('mode') == 'enforcing' + - import_tasks: setgid.yml + - import_tasks: no_log.yml delegate_to: localhost @@ -122,6 +130,11 @@ remove: yes force: yes + - name: Remove group for remote unprivileged user + group: + name: '{{ remote_unprivileged_user_group }}' + state: absent + - name: Remove sudoers.d file file: path: "{{ sudoers_d_file }}" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/test/integration/targets/copy/tasks/setgid.yml new/ansible_core-2.17.4/test/integration/targets/copy/tasks/setgid.yml --- old/ansible_core-2.17.3/test/integration/targets/copy/tasks/setgid.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/ansible_core-2.17.4/test/integration/targets/copy/tasks/setgid.yml 2024-09-09 21:26:24.000000000 +0200 @@ -0,0 +1,27 @@ +- block: + - name: Create test directory + file: + path: "{{ remote_tmp_dir }}/test_setgid" + state: directory + mode: '2750' + recurse: yes + owner: '{{ remote_unprivileged_user }}' + group: '{{ remote_unprivileged_user_group }}' + + - name: Test creating a file respects setgid on parent dir + copy: + content: | + test file + dest: "{{ remote_tmp_dir }}/test_setgid/test.txt" + + - stat: + path: "{{ remote_tmp_dir }}/test_setgid/test.txt" + register: result + + - assert: + that: + - result.stat.gr_name == remote_unprivileged_user_group + always: + - file: + path: "{{ remote_tmp_dir }}/test_setgid" + state: absent diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/test/integration/targets/include_import/null_filename/tasks.yml new/ansible_core-2.17.4/test/integration/targets/include_import/null_filename/tasks.yml --- old/ansible_core-2.17.3/test/integration/targets/include_import/null_filename/tasks.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/ansible_core-2.17.4/test/integration/targets/include_import/null_filename/tasks.yml 2024-09-09 21:26:24.000000000 +0200 @@ -0,0 +1,5 @@ +- name: ping task + ansible.builtin.ping: + +- name: invalid include_task definition + ansible.builtin.include_tasks: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/test/integration/targets/include_import/runme.sh new/ansible_core-2.17.4/test/integration/targets/include_import/runme.sh --- old/ansible_core-2.17.3/test/integration/targets/include_import/runme.sh 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/test/integration/targets/include_import/runme.sh 2024-09-09 21:26:24.000000000 +0200 @@ -148,3 +148,9 @@ # https://github.com/ansible/ansible/issues/73657 ansible-playbook issue73657.yml 2>&1 | tee issue73657.out test "$(grep -c 'SHOULD_NOT_EXECUTE' issue73657.out)" = 0 + +# https://github.com/ansible/ansible/issues/83874 +ansible-playbook test_null_include_filename.yml 2>&1 | tee test_null_include_filename.out +test "$(grep -c 'ERROR! No file specified for ansible.builtin.include_tasks' test_null_include_filename.out)" = 1 +test "$(grep -c 'The error appears to be in '\''.*/include_import/null_filename/tasks.yml'\'': line 4, column 3.*' test_null_include_filename.out)" = 1 +test "$(grep -c '\- name: invalid include_task definition' test_null_include_filename.out)" = 1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/test/integration/targets/include_import/test_null_include_filename.yml new/ansible_core-2.17.4/test/integration/targets/include_import/test_null_include_filename.yml --- old/ansible_core-2.17.3/test/integration/targets/include_import/test_null_include_filename.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/ansible_core-2.17.4/test/integration/targets/include_import/test_null_include_filename.yml 2024-09-09 21:26:24.000000000 +0200 @@ -0,0 +1,7 @@ +- name: Test include failure with invalid included include_task + hosts: localhost + gather_facts: false + + tasks: + - ansible.builtin.include_tasks: + file: null_filename/tasks.yml diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/test/integration/targets/lookup_csvfile/tasks/main.yml new/ansible_core-2.17.4/test/integration/targets/lookup_csvfile/tasks/main.yml --- old/ansible_core-2.17.3/test/integration/targets/lookup_csvfile/tasks/main.yml 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/test/integration/targets/lookup_csvfile/tasks/main.yml 2024-09-09 21:26:24.000000000 +0200 @@ -4,6 +4,12 @@ ignore_errors: yes register: no_keyword +- name: using modern syntax but missing keyword + set_fact: + this_will_error: "{{ lookup('csvfile', file='people.csv', delimiter=' ', col=1) }}" + ignore_errors: yes + register: modern_no_keyword + - name: extra arg in k=v syntax (deprecated) set_fact: this_will_error: "{{ lookup('csvfile', 'foo file=people.csv delimiter=, col=1 thisarg=doesnotexist') }}" @@ -27,6 +33,9 @@ - no_keyword is failed - > "Search key is required but was not found" in no_keyword.msg + - modern_no_keyword is failed + - > + "Search key is required but was not found" in modern_no_keyword.msg - invalid_arg is failed - invalid_arg2 is failed - > diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/test/integration/targets/lookup_first_found/roles/a/tasks/main.yml new/ansible_core-2.17.4/test/integration/targets/lookup_first_found/roles/a/tasks/main.yml --- old/ansible_core-2.17.3/test/integration/targets/lookup_first_found/roles/a/tasks/main.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/ansible_core-2.17.4/test/integration/targets/lookup_first_found/roles/a/tasks/main.yml 2024-09-09 21:26:24.000000000 +0200 @@ -0,0 +1 @@ +- include_tasks: subdir/main.yml diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/test/integration/targets/lookup_first_found/roles/a/tasks/subdir/main.yml new/ansible_core-2.17.4/test/integration/targets/lookup_first_found/roles/a/tasks/subdir/main.yml --- old/ansible_core-2.17.3/test/integration/targets/lookup_first_found/roles/a/tasks/subdir/main.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/ansible_core-2.17.4/test/integration/targets/lookup_first_found/roles/a/tasks/subdir/main.yml 2024-09-09 21:26:24.000000000 +0200 @@ -0,0 +1,7 @@ +- assert: + that: + - "lookup('first_found', task_adjacent) is is_file" + vars: + task_adjacent: + - files: + - relative diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/test/integration/targets/lookup_first_found/tasks/main.yml new/ansible_core-2.17.4/test/integration/targets/lookup_first_found/tasks/main.yml --- old/ansible_core-2.17.3/test/integration/targets/lookup_first_found/tasks/main.yml 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/test/integration/targets/lookup_first_found/tasks/main.yml 2024-09-09 21:26:24.000000000 +0200 @@ -152,3 +152,7 @@ assert: that: - q('first_found', ['/nonexistant'], skip=True) == [] + +- name: Test relative paths in roles + include_role: + role: "{{ role_path }}/roles/a" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/test/integration/targets/loops/tasks/main.yml new/ansible_core-2.17.4/test/integration/targets/loops/tasks/main.yml --- old/ansible_core-2.17.3/test/integration/targets/loops/tasks/main.yml 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/test/integration/targets/loops/tasks/main.yml 2024-09-09 21:26:24.000000000 +0200 @@ -405,3 +405,20 @@ - assert: that: - foo[0] == 'foo1.0' + +# https://github.com/ansible/ansible/issues/83619 +- command: "echo {{ item }}" + register: r + loop: + - changed + - skipped + loop_control: + label: "{{ r.stdout }}" + when: + - item == "changed" + ignore_errors: true + +- name: test that the second iteration result was stored, since it was skipped no stdout should be present there + assert: + that: + - "r['results'][1]['msg'] is contains(\"no attribute 'stdout'\")" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/test/integration/targets/strategy_host_pinned/aliases new/ansible_core-2.17.4/test/integration/targets/strategy_host_pinned/aliases --- old/ansible_core-2.17.3/test/integration/targets/strategy_host_pinned/aliases 1970-01-01 01:00:00.000000000 +0100 +++ new/ansible_core-2.17.4/test/integration/targets/strategy_host_pinned/aliases 2024-09-09 21:26:24.000000000 +0200 @@ -0,0 +1 @@ +shippable/posix/group5 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/test/integration/targets/strategy_host_pinned/callback_plugins/callback_host_count.py new/ansible_core-2.17.4/test/integration/targets/strategy_host_pinned/callback_plugins/callback_host_count.py --- old/ansible_core-2.17.3/test/integration/targets/strategy_host_pinned/callback_plugins/callback_host_count.py 1970-01-01 01:00:00.000000000 +0100 +++ new/ansible_core-2.17.4/test/integration/targets/strategy_host_pinned/callback_plugins/callback_host_count.py 2024-09-09 21:26:24.000000000 +0200 @@ -0,0 +1,43 @@ +# (c) 2024 Ansible Project +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import annotations + +from ansible.plugins.callback import CallbackBase + + +class CallbackModule(CallbackBase): + CALLBACK_VERSION = 2.0 + CALLBACK_TYPE = 'stdout' + CALLBACK_NAME = 'callback_host_count' + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self._executing_hosts_counter = 0 + + def v2_playbook_on_task_start(self, task, is_conditional): + self._display.display(task.name or task.action) + + if task.name == "start": + self._executing_hosts_counter += 1 + + # NOTE assumes 2 forks + num_forks = 2 + if self._executing_hosts_counter > num_forks: + # Exception is caught and turned into just a warning in TQM, + # so raise BaseException to fail the test + # To prevent seeing false positives in case the exception handling + # in TQM is changed and BaseException is swallowed, print something + # and ensure the test fails in runme.sh in such a case. + self._display.display("host_pinned_test_failed") + raise BaseException( + "host_pinned test failed, number of hosts executing: " + f"{self._executing_hosts_counter}, expected: {num_forks}" + ) + + def v2_playbook_on_handler_task_start(self, task): + self._display.display(task.name or task.action) + + def v2_runner_on_ok(self, result): + if result._task.name == "end": + self._executing_hosts_counter -= 1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/test/integration/targets/strategy_host_pinned/hosts new/ansible_core-2.17.4/test/integration/targets/strategy_host_pinned/hosts --- old/ansible_core-2.17.3/test/integration/targets/strategy_host_pinned/hosts 1970-01-01 01:00:00.000000000 +0100 +++ new/ansible_core-2.17.4/test/integration/targets/strategy_host_pinned/hosts 2024-09-09 21:26:24.000000000 +0200 @@ -0,0 +1,14 @@ +localhost0 +localhost1 +localhost2 +localhost3 +localhost4 +localhost5 +localhost6 +localhost7 +localhost8 +localhost9 + +[all:vars] +ansible_connection=local +ansible_python_interpreter={{ansible_playbook_python}} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/test/integration/targets/strategy_host_pinned/playbook.yml new/ansible_core-2.17.4/test/integration/targets/strategy_host_pinned/playbook.yml --- old/ansible_core-2.17.3/test/integration/targets/strategy_host_pinned/playbook.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/ansible_core-2.17.4/test/integration/targets/strategy_host_pinned/playbook.yml 2024-09-09 21:26:24.000000000 +0200 @@ -0,0 +1,46 @@ +# README - even the name of the tasks matter in this test, see callback_plugins/callback_host_count.py +- hosts: all + gather_facts: false + strategy: host_pinned + pre_tasks: + # by executing in pre_tasks we ensure that "start" is the first task in the play, + # not an implicit "meta: flush_handlers" after pre_tasks + - name: start + debug: + msg: start + + - ping: + + - meta: noop + post_tasks: + # notifying a handler in post_tasks ensures the handler is the last task in the play, + # not an implicit "meta: flush_handlers" after post_tasks + - debug: + changed_when: true + notify: end + handlers: + - name: end + debug: + msg: end + +- hosts: localhost0,localhost1,localhost2 + gather_facts: false + strategy: host_pinned + pre_tasks: + - name: start + debug: + msg: start + + - command: sleep 3 + when: inventory_hostname == "localhost0" + + - meta: noop + - meta: noop + post_tasks: + - debug: + changed_when: true + notify: end + handlers: + - name: end + debug: + msg: end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/test/integration/targets/strategy_host_pinned/runme.sh new/ansible_core-2.17.4/test/integration/targets/strategy_host_pinned/runme.sh --- old/ansible_core-2.17.3/test/integration/targets/strategy_host_pinned/runme.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/ansible_core-2.17.4/test/integration/targets/strategy_host_pinned/runme.sh 2024-09-09 21:26:24.000000000 +0200 @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +set -o pipefail + +export ANSIBLE_STDOUT_CALLBACK=callback_host_count + +# the number of forks matter, see callback_plugins/callback_host_count.py +ansible-playbook --inventory hosts --forks 2 playbook.yml | tee "${OUTPUT_DIR}/out.txt" + +[ "$(grep -c 'host_pinned_test_failed' "${OUTPUT_DIR}/out.txt")" -eq 0 ] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/test/integration/targets/win_fetch/aliases new/ansible_core-2.17.4/test/integration/targets/win_fetch/aliases --- old/ansible_core-2.17.3/test/integration/targets/win_fetch/aliases 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/test/integration/targets/win_fetch/aliases 2024-09-09 21:26:24.000000000 +0200 @@ -1 +1,2 @@ shippable/windows/group1 +shippable/windows/smoketest diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/test/lib/ansible_test/_util/controller/sanity/code-smell/runtime-metadata.py new/ansible_core-2.17.4/test/lib/ansible_test/_util/controller/sanity/code-smell/runtime-metadata.py --- old/ansible_core-2.17.3/test/lib/ansible_test/_util/controller/sanity/code-smell/runtime-metadata.py 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/test/lib/ansible_test/_util/controller/sanity/code-smell/runtime-metadata.py 2024-09-09 21:26:24.000000000 +0200 @@ -123,7 +123,9 @@ # noinspection PyBroadException try: result = collection_detail.read_manifest_json('.') or collection_detail.read_galaxy_yml('.') - return SemanticVersion(result['version']) + version = SemanticVersion() + version.parse(result['version']) + return version except Exception: # pylint: disable=broad-except # We do not care why it fails, in case we cannot get the version # just return None to indicate "we don't know". diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/test/sanity/code-smell/package-data.py new/ansible_core-2.17.4/test/sanity/code-smell/package-data.py --- old/ansible_core-2.17.3/test/sanity/code-smell/package-data.py 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/test/sanity/code-smell/package-data.py 2024-09-09 21:26:24.000000000 +0200 @@ -95,7 +95,7 @@ def build(source_dir: str, tmp_dir: str) -> tuple[pathlib.Path, pathlib.Path]: """Create a sdist and wheel.""" create = subprocess.run( - [sys.executable, '-m', 'build', '--no-isolation', '--outdir', tmp_dir], + [sys.executable, '-m', 'build', '--outdir', tmp_dir], stdin=subprocess.DEVNULL, capture_output=True, text=True, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/test/units/plugins/connection/test_psrp.py new/ansible_core-2.17.4/test/units/plugins/connection/test_psrp.py --- old/ansible_core-2.17.3/test/units/plugins/connection/test_psrp.py 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/test/units/plugins/connection/test_psrp.py 2024-09-09 21:26:24.000000000 +0200 @@ -220,12 +220,13 @@ pc = PlayContext() new_stdin = StringIO() - conn = connection_loader.get('psrp', pc, new_stdin) - conn.set_options(var_options={'_extras': {'ansible_psrp_mock_test3': True}}) + for conn_name in ('psrp', 'ansible.legacy.psrp'): + conn = connection_loader.get(conn_name, pc, new_stdin) + conn.set_options(var_options={'_extras': {'ansible_psrp_mock_test3': True}}) - mock_display = MagicMock() - monkeypatch.setattr(Display, "warning", mock_display) - conn._build_kwargs() + mock_display = MagicMock() + monkeypatch.setattr(Display, "warning", mock_display) + conn._build_kwargs() - assert mock_display.call_args[0][0] == \ - 'ansible_psrp_mock_test3 is unsupported by the current psrp version installed' + assert mock_display.call_args[0][0] == \ + 'ansible_psrp_mock_test3 is unsupported by the current psrp version installed' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ansible_core-2.17.3/test/units/plugins/shell/test_powershell.py new/ansible_core-2.17.4/test/units/plugins/shell/test_powershell.py --- old/ansible_core-2.17.3/test/units/plugins/shell/test_powershell.py 2024-08-12 23:17:08.000000000 +0200 +++ new/ansible_core-2.17.4/test/units/plugins/shell/test_powershell.py 2024-09-09 21:26:24.000000000 +0200 @@ -1,5 +1,7 @@ from __future__ import annotations +import pytest + from ansible.plugins.shell.powershell import _parse_clixml, ShellModule @@ -27,7 +29,8 @@ b'<S S="Error">At line:1 char:1_x000D__x000A_</S>' \ b'<S S="Error">+ fake cmdlet_x000D__x000A_</S><S S="Error">+ ~~~~_x000D__x000A_</S>' \ b'<S S="Error"> + CategoryInfo : ObjectNotFound: (fake:String) [], CommandNotFoundException_x000D__x000A_</S>' \ - b'<S S="Error"> + FullyQualifiedErrorId : CommandNotFoundException_x000D__x000A_</S><S S="Error"> _x000D__x000A_</S>' \ + b'<S S="Error"> + FullyQualifiedErrorId : CommandNotFoundException_x000D__x000A_</S>' \ + b'<S S="Error"> _x000D__x000A_</S>' \ b'</Objs>' expected = b"fake : The term 'fake' is not recognized as the name of a cmdlet. Check \r\n" \ b"the spelling of the name, or if a path was included.\r\n" \ @@ -35,7 +38,8 @@ b"+ fake cmdlet\r\n" \ b"+ ~~~~\r\n" \ b" + CategoryInfo : ObjectNotFound: (fake:String) [], CommandNotFoundException\r\n" \ - b" + FullyQualifiedErrorId : CommandNotFoundException\r\n " + b" + FullyQualifiedErrorId : CommandNotFoundException\r\n" \ + b" \r\n" actual = _parse_clixml(single_stream) assert actual == expected @@ -49,8 +53,9 @@ b'<S S="Error"> + CategoryInfo : ObjectNotFound: (fake:String) [], CommandNotFoundException_x000D__x000A_</S>' \ b'<S S="Error"> + FullyQualifiedErrorId : CommandNotFoundException_x000D__x000A_</S><S S="Error"> _x000D__x000A_</S>' \ b'<S S="Info">hi info</S>' \ + b'<S S="Info">other</S>' \ b'</Objs>' - expected = b"hi info" + expected = b"hi infoother" actual = _parse_clixml(multiple_stream, stream="Info") assert actual == expected @@ -74,6 +79,32 @@ assert actual == expected +@pytest.mark.parametrize('clixml, expected', [ + ('', ''), + ('just newline _x000A_', 'just newline \n'), + ('surrogate pair _xD83C__xDFB5_', 'surrogate pair ðµ'), + ('null char _x0000_', 'null char \0'), + ('normal char _x0061_', 'normal char a'), + ('escaped literal _x005F_x005F_', 'escaped literal _x005F_'), + ('underscope before escape _x005F__x000A_', 'underscope before escape _\n'), + ('surrogate high _xD83C_', 'surrogate high \uD83C'), + ('surrogate low _xDFB5_', 'surrogate low \uDFB5'), + ('lower case hex _x005f_', 'lower case hex _'), + ('invalid hex _x005G_', 'invalid hex _x005G_'), +]) +def test_parse_clixml_with_comlex_escaped_chars(clixml, expected): + clixml_data = ( + '<# CLIXML\r\n' + '<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">' + f'<S S="Error">{clixml}</S>' + '</Objs>' + ).encode() + b_expected = expected.encode(errors="surrogatepass") + + actual = _parse_clixml(clixml_data) + assert actual == b_expected + + def test_join_path_unc(): pwsh = ShellModule() unc_path_parts = ['\\\\host\\share\\dir1\\\\dir2\\', '\\dir3/dir4', 'dir5', 'dir6\\'] ++++++ ansible_core-2.17.3.tar.gz.sha256 -> ansible_core-2.17.4.tar.gz.sha256 ++++++ --- /work/SRC/openSUSE:Factory/ansible-core/ansible_core-2.17.3.tar.gz.sha256 2024-08-15 09:58:44.568011275 +0200 +++ /work/SRC/openSUSE:Factory/.ansible-core.new.29891/ansible_core-2.17.4.tar.gz.sha256 2024-09-16 17:40:50.419508643 +0200 @@ -1 +1 @@ -917557065339fe36e7078e9bea47eefab6d6877f3bd435fa5f0d766d04c58485 ansible_core-2.17.3.tar.gz +44a1f30076796536ba2455cad18d36e62870f04e632e3ca2ebe970d7beacf24d ansible_core-2.17.4.tar.gz