ansible-core 2.15.3rc1__py3-none-any.whl → 2.15.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ansible-core might be problematic. Click here for more details.

Files changed (27) hide show
  1. ansible/galaxy/role.py +33 -1
  2. ansible/module_utils/ansible_release.py +1 -1
  3. ansible/module_utils/basic.py +68 -55
  4. ansible/module_utils/csharp/Ansible.AccessToken.cs +0 -3
  5. ansible/module_utils/csharp/Ansible.Become.cs +0 -4
  6. ansible/module_utils/csharp/Ansible.Privilege.cs +1 -3
  7. ansible/module_utils/csharp/Ansible.Process.cs +0 -2
  8. ansible/playbook/role_include.py +1 -1
  9. ansible/plugins/filter/encryption.py +18 -4
  10. ansible/plugins/lookup/first_found.py +3 -0
  11. ansible/plugins/strategy/__init__.py +9 -2
  12. ansible/release.py +1 -1
  13. ansible/utils/display.py +2 -0
  14. {ansible_core-2.15.3rc1.dist-info → ansible_core-2.15.4.dist-info}/METADATA +1 -1
  15. {ansible_core-2.15.3rc1.dist-info → ansible_core-2.15.4.dist-info}/RECORD +27 -27
  16. {ansible_core-2.15.3rc1.dist-info → ansible_core-2.15.4.dist-info}/WHEEL +1 -1
  17. ansible_test/_internal/ansible_util.py +56 -3
  18. ansible_test/_internal/commands/sanity/bin_symlinks.py +2 -2
  19. ansible_test/_internal/commands/sanity/mypy.py +2 -2
  20. ansible_test/_internal/commands/sanity/validate_modules.py +5 -1
  21. ansible_test/_internal/constants.py +1 -0
  22. ansible_test/_internal/delegation.py +5 -2
  23. ansible_test/_internal/util.py +0 -2
  24. {ansible_core-2.15.3rc1.data → ansible_core-2.15.4.data}/scripts/ansible-test +0 -0
  25. {ansible_core-2.15.3rc1.dist-info → ansible_core-2.15.4.dist-info}/COPYING +0 -0
  26. {ansible_core-2.15.3rc1.dist-info → ansible_core-2.15.4.dist-info}/entry_points.txt +0 -0
  27. {ansible_core-2.15.3rc1.dist-info → ansible_core-2.15.4.dist-info}/top_level.txt +0 -0
ansible/galaxy/role.py CHANGED
@@ -24,6 +24,7 @@ __metaclass__ = type
24
24
 
25
25
  import errno
26
26
  import datetime
27
+ import functools
27
28
  import os
28
29
  import tarfile
29
30
  import tempfile
@@ -45,6 +46,32 @@ from ansible.utils.display import Display
45
46
  display = Display()
46
47
 
47
48
 
49
+ @functools.cache
50
+ def _check_working_data_filter() -> bool:
51
+ """
52
+ Check if tarfile.data_filter implementation is working
53
+ for the current Python version or not
54
+ """
55
+
56
+ # Implemented the following code to circumvent broken implementation of data_filter
57
+ # in tarfile. See for more information - https://github.com/python/cpython/issues/107845
58
+ # deprecated: description='probing broken data filter implementation' python_version='3.11'
59
+ ret = False
60
+ if hasattr(tarfile, 'data_filter'):
61
+ # We explicitly check if tarfile.data_filter is broken or not
62
+ ti = tarfile.TarInfo('docs/README.md')
63
+ ti.type = tarfile.SYMTYPE
64
+ ti.linkname = '../README.md'
65
+
66
+ try:
67
+ tarfile.data_filter(ti, '/foo')
68
+ except tarfile.LinkOutsideDestinationError:
69
+ pass
70
+ else:
71
+ ret = True
72
+ return ret
73
+
74
+
48
75
  class GalaxyRole(object):
49
76
 
50
77
  SUPPORTED_SCMS = set(['git', 'hg'])
@@ -379,7 +406,12 @@ class GalaxyRole(object):
379
406
  if n_part != '..' and not n_part.startswith('~') and '$' not in n_part:
380
407
  n_final_parts.append(n_part)
381
408
  member.name = os.path.join(*n_final_parts)
382
- role_tar_file.extract(member, to_native(self.path))
409
+
410
+ if _check_working_data_filter():
411
+ # deprecated: description='extract fallback without filter' python_version='3.11'
412
+ role_tar_file.extract(member, to_native(self.path), filter='data') # type: ignore[call-arg]
413
+ else:
414
+ role_tar_file.extract(member, to_native(self.path))
383
415
 
384
416
  # write out the install info file for later use
385
417
  self._write_galaxy_install_info()
@@ -19,6 +19,6 @@
19
19
  from __future__ import (absolute_import, division, print_function)
20
20
  __metaclass__ = type
21
21
 
22
- __version__ = '2.15.3rc1'
22
+ __version__ = '2.15.4'
23
23
  __author__ = 'Ansible, Inc.'
24
24
  __codename__ = "Ten Years Gone"
@@ -1852,6 +1852,14 @@ class AnsibleModule(object):
1852
1852
  '''
1853
1853
  Execute a command, returns rc, stdout, and stderr.
1854
1854
 
1855
+ The mechanism of this method for reading stdout and stderr differs from
1856
+ that of CPython subprocess.Popen.communicate, in that this method will
1857
+ stop reading once the spawned command has exited and stdout and stderr
1858
+ have been consumed, as opposed to waiting until stdout/stderr are
1859
+ closed. This can be an important distinction, when taken into account
1860
+ that a forked or backgrounded process may hold stdout or stderr open
1861
+ for longer than the spawned command.
1862
+
1855
1863
  :arg args: is the command to run
1856
1864
  * If args is a list, the command will be run with shell=False.
1857
1865
  * If args is a string and use_unsafe_shell=False it will split args to a list and run with shell=False
@@ -2031,17 +2039,17 @@ class AnsibleModule(object):
2031
2039
  if before_communicate_callback:
2032
2040
  before_communicate_callback(cmd)
2033
2041
 
2034
- # the communication logic here is essentially taken from that
2035
- # of the _communicate() function in ssh.py
2036
-
2037
2042
  stdout = b''
2038
2043
  stderr = b''
2039
- try:
2040
- selector = selectors.DefaultSelector()
2041
- except (IOError, OSError):
2042
- # Failed to detect default selector for the given platform
2043
- # Select PollSelector which is supported by major platforms
2044
+
2045
+ # Mirror the CPython subprocess logic and preference for the selector to use.
2046
+ # poll/select have the advantage of not requiring any extra file
2047
+ # descriptor, contrarily to epoll/kqueue (also, they require a single
2048
+ # syscall).
2049
+ if hasattr(selectors, 'PollSelector'):
2044
2050
  selector = selectors.PollSelector()
2051
+ else:
2052
+ selector = selectors.SelectSelector()
2045
2053
 
2046
2054
  if data:
2047
2055
  if not binary_data:
@@ -2049,53 +2057,58 @@ class AnsibleModule(object):
2049
2057
  if isinstance(data, text_type):
2050
2058
  data = to_bytes(data)
2051
2059
 
2052
- if not prompt_re:
2053
- stdout, stderr = cmd.communicate(input=data)
2054
- else:
2055
- # We only need this to look for a prompt, to abort instead of hanging
2056
- selector.register(cmd.stdout, selectors.EVENT_READ)
2057
- selector.register(cmd.stderr, selectors.EVENT_READ)
2058
- if os.name == 'posix':
2059
- fcntl.fcntl(cmd.stdout.fileno(), fcntl.F_SETFL, fcntl.fcntl(cmd.stdout.fileno(), fcntl.F_GETFL) | os.O_NONBLOCK)
2060
- fcntl.fcntl(cmd.stderr.fileno(), fcntl.F_SETFL, fcntl.fcntl(cmd.stderr.fileno(), fcntl.F_GETFL) | os.O_NONBLOCK)
2061
-
2062
- if data:
2063
- cmd.stdin.write(data)
2064
- cmd.stdin.close()
2065
-
2066
- while True:
2067
- events = selector.select(1)
2068
- for key, event in events:
2069
- b_chunk = key.fileobj.read()
2070
- if b_chunk == b(''):
2071
- selector.unregister(key.fileobj)
2072
- if key.fileobj == cmd.stdout:
2073
- stdout += b_chunk
2074
- elif key.fileobj == cmd.stderr:
2075
- stderr += b_chunk
2076
- # if we're checking for prompts, do it now
2077
- if prompt_re:
2078
- if prompt_re.search(stdout) and not data:
2079
- if encoding:
2080
- stdout = to_native(stdout, encoding=encoding, errors=errors)
2081
- return (257, stdout, "A prompt was encountered while running a command, but no input data was specified")
2082
- # only break out if no pipes are left to read or
2083
- # the pipes are completely read and
2084
- # the process is terminated
2085
- if (not events or not selector.get_map()) and cmd.poll() is not None:
2086
- break
2087
- # No pipes are left to read but process is not yet terminated
2088
- # Only then it is safe to wait for the process to be finished
2089
- # NOTE: Actually cmd.poll() is always None here if no selectors are left
2090
- elif not selector.get_map() and cmd.poll() is None:
2091
- cmd.wait()
2092
- # The process is terminated. Since no pipes to read from are
2093
- # left, there is no need to call select() again.
2094
- break
2095
-
2096
- cmd.stdout.close()
2097
- cmd.stderr.close()
2098
- selector.close()
2060
+ selector.register(cmd.stdout, selectors.EVENT_READ)
2061
+ selector.register(cmd.stderr, selectors.EVENT_READ)
2062
+
2063
+ if os.name == 'posix':
2064
+ fcntl.fcntl(cmd.stdout.fileno(), fcntl.F_SETFL, fcntl.fcntl(cmd.stdout.fileno(), fcntl.F_GETFL) | os.O_NONBLOCK)
2065
+ fcntl.fcntl(cmd.stderr.fileno(), fcntl.F_SETFL, fcntl.fcntl(cmd.stderr.fileno(), fcntl.F_GETFL) | os.O_NONBLOCK)
2066
+
2067
+ if data:
2068
+ cmd.stdin.write(data)
2069
+ cmd.stdin.close()
2070
+
2071
+ while True:
2072
+ # A timeout of 1 is both a little short and a little long.
2073
+ # With None we could deadlock, with a lower value we would
2074
+ # waste cycles. As it is, this is a mild inconvenience if
2075
+ # we need to exit, and likely doesn't waste too many cycles
2076
+ events = selector.select(1)
2077
+ stdout_changed = False
2078
+ for key, event in events:
2079
+ b_chunk = key.fileobj.read(32768)
2080
+ if not b_chunk:
2081
+ selector.unregister(key.fileobj)
2082
+ elif key.fileobj == cmd.stdout:
2083
+ stdout += b_chunk
2084
+ stdout_changed = True
2085
+ elif key.fileobj == cmd.stderr:
2086
+ stderr += b_chunk
2087
+
2088
+ # if we're checking for prompts, do it now, but only if stdout
2089
+ # actually changed since the last loop
2090
+ if prompt_re and stdout_changed and prompt_re.search(stdout) and not data:
2091
+ if encoding:
2092
+ stdout = to_native(stdout, encoding=encoding, errors=errors)
2093
+ return (257, stdout, "A prompt was encountered while running a command, but no input data was specified")
2094
+
2095
+ # break out if no pipes are left to read or the pipes are completely read
2096
+ # and the process is terminated
2097
+ if (not events or not selector.get_map()) and cmd.poll() is not None:
2098
+ break
2099
+
2100
+ # No pipes are left to read but process is not yet terminated
2101
+ # Only then it is safe to wait for the process to be finished
2102
+ # NOTE: Actually cmd.poll() is always None here if no selectors are left
2103
+ elif not selector.get_map() and cmd.poll() is None:
2104
+ cmd.wait()
2105
+ # The process is terminated. Since no pipes to read from are
2106
+ # left, there is no need to call select() again.
2107
+ break
2108
+
2109
+ cmd.stdout.close()
2110
+ cmd.stderr.close()
2111
+ selector.close()
2099
2112
 
2100
2113
  rc = cmd.returncode
2101
2114
  except (OSError, IOError) as e:
@@ -2,7 +2,6 @@ using Microsoft.Win32.SafeHandles;
2
2
  using System;
3
3
  using System.Collections.Generic;
4
4
  using System.Linq;
5
- using System.Runtime.ConstrainedExecution;
6
5
  using System.Runtime.InteropServices;
7
6
  using System.Security.Principal;
8
7
  using System.Text;
@@ -123,7 +122,6 @@ namespace Ansible.AccessToken
123
122
  base.SetHandle(handle);
124
123
  }
125
124
 
126
- [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
127
125
  protected override bool ReleaseHandle()
128
126
  {
129
127
  Marshal.FreeHGlobal(handle);
@@ -247,7 +245,6 @@ namespace Ansible.AccessToken
247
245
  public SafeNativeHandle() : base(true) { }
248
246
  public SafeNativeHandle(IntPtr handle) : base(true) { this.handle = handle; }
249
247
 
250
- [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
251
248
  protected override bool ReleaseHandle()
252
249
  {
253
250
  return NativeMethods.CloseHandle(handle);
@@ -4,7 +4,6 @@ using System.Collections;
4
4
  using System.Collections.Generic;
5
5
  using System.IO;
6
6
  using System.Linq;
7
- using System.Runtime.ConstrainedExecution;
8
7
  using System.Runtime.InteropServices;
9
8
  using System.Security.AccessControl;
10
9
  using System.Security.Principal;
@@ -175,7 +174,6 @@ namespace Ansible.Become
175
174
  {
176
175
  public SafeLsaHandle() : base(true) { }
177
176
 
178
- [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
179
177
  protected override bool ReleaseHandle()
180
178
  {
181
179
  UInt32 res = NativeMethods.LsaDeregisterLogonProcess(handle);
@@ -187,7 +185,6 @@ namespace Ansible.Become
187
185
  {
188
186
  public SafeLsaMemoryBuffer() : base(true) { }
189
187
 
190
- [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
191
188
  protected override bool ReleaseHandle()
192
189
  {
193
190
  UInt32 res = NativeMethods.LsaFreeReturnBuffer(handle);
@@ -200,7 +197,6 @@ namespace Ansible.Become
200
197
  public NoopSafeHandle() : base(IntPtr.Zero, false) { }
201
198
  public override bool IsInvalid { get { return false; } }
202
199
 
203
- [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
204
200
  protected override bool ReleaseHandle() { return true; }
205
201
  }
206
202
 
@@ -3,7 +3,6 @@ using System;
3
3
  using System.Collections;
4
4
  using System.Collections.Generic;
5
5
  using System.Linq;
6
- using System.Runtime.ConstrainedExecution;
7
6
  using System.Runtime.InteropServices;
8
7
  using System.Security.Principal;
9
8
  using System.Text;
@@ -92,7 +91,6 @@ namespace Ansible.Privilege
92
91
  {
93
92
  base.SetHandle(handle);
94
93
  }
95
- [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
96
94
  protected override bool ReleaseHandle()
97
95
  {
98
96
  Marshal.FreeHGlobal(handle);
@@ -104,7 +102,7 @@ namespace Ansible.Privilege
104
102
  {
105
103
  public SafeNativeHandle() : base(true) { }
106
104
  public SafeNativeHandle(IntPtr handle) : base(true) { this.handle = handle; }
107
- [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
105
+
108
106
  protected override bool ReleaseHandle()
109
107
  {
110
108
  return NativeMethods.CloseHandle(handle);
@@ -3,7 +3,6 @@ using System;
3
3
  using System.Collections;
4
4
  using System.IO;
5
5
  using System.Linq;
6
- using System.Runtime.ConstrainedExecution;
7
6
  using System.Runtime.InteropServices;
8
7
  using System.Text;
9
8
  using System.Threading;
@@ -176,7 +175,6 @@ namespace Ansible.Process
176
175
  base.SetHandle(handle);
177
176
  }
178
177
 
179
- [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
180
178
  protected override bool ReleaseHandle()
181
179
  {
182
180
  Marshal.FreeHGlobal(handle);
@@ -113,7 +113,7 @@ class IncludeRole(TaskInclude):
113
113
  b.collections = actual_role.collections
114
114
 
115
115
  # updated available handlers in play
116
- handlers = actual_role.get_handler_blocks(play=myplay)
116
+ handlers = actual_role.get_handler_blocks(play=myplay, dep_chain=dep_chain)
117
117
  for h in handlers:
118
118
  h._parent = p_block
119
119
  myplay.handlers = myplay.handlers + handlers
@@ -17,7 +17,7 @@ from ansible.utils.display import Display
17
17
  display = Display()
18
18
 
19
19
 
20
- def do_vault(data, secret, salt=None, vaultid='filter_default', wrap_object=False):
20
+ def do_vault(data, secret, salt=None, vault_id='filter_default', wrap_object=False, vaultid=None):
21
21
 
22
22
  if not isinstance(secret, (string_types, binary_type, Undefined)):
23
23
  raise AnsibleFilterTypeError("Secret passed is required to be a string, instead we got: %s" % type(secret))
@@ -25,11 +25,18 @@ def do_vault(data, secret, salt=None, vaultid='filter_default', wrap_object=Fals
25
25
  if not isinstance(data, (string_types, binary_type, Undefined)):
26
26
  raise AnsibleFilterTypeError("Can only vault strings, instead we got: %s" % type(data))
27
27
 
28
+ if vaultid is not None:
29
+ display.deprecated("Use of undocumented 'vaultid', use 'vault_id' instead", version='2.20')
30
+ if vault_id == 'filter_default':
31
+ vault_id = vaultid
32
+ else:
33
+ display.warning("Ignoring vaultid as vault_id is already set.")
34
+
28
35
  vault = ''
29
36
  vs = VaultSecret(to_bytes(secret))
30
37
  vl = VaultLib()
31
38
  try:
32
- vault = vl.encrypt(to_bytes(data), vs, vaultid, salt)
39
+ vault = vl.encrypt(to_bytes(data), vs, vault_id, salt)
33
40
  except UndefinedError:
34
41
  raise
35
42
  except Exception as e:
@@ -43,7 +50,7 @@ def do_vault(data, secret, salt=None, vaultid='filter_default', wrap_object=Fals
43
50
  return vault
44
51
 
45
52
 
46
- def do_unvault(vault, secret, vaultid='filter_default'):
53
+ def do_unvault(vault, secret, vault_id='filter_default', vaultid=None):
47
54
 
48
55
  if not isinstance(secret, (string_types, binary_type, Undefined)):
49
56
  raise AnsibleFilterTypeError("Secret passed is required to be as string, instead we got: %s" % type(secret))
@@ -51,9 +58,16 @@ def do_unvault(vault, secret, vaultid='filter_default'):
51
58
  if not isinstance(vault, (string_types, binary_type, AnsibleVaultEncryptedUnicode, Undefined)):
52
59
  raise AnsibleFilterTypeError("Vault should be in the form of a string, instead we got: %s" % type(vault))
53
60
 
61
+ if vaultid is not None:
62
+ display.deprecated("Use of undocumented 'vaultid', use 'vault_id' instead", version='2.20')
63
+ if vault_id == 'filter_default':
64
+ vault_id = vaultid
65
+ else:
66
+ display.warning("Ignoring vaultid as vault_id is already set.")
67
+
54
68
  data = ''
55
69
  vs = VaultSecret(to_bytes(secret))
56
- vl = VaultLib([(vaultid, vs)])
70
+ vl = VaultLib([(vault_id, vs)])
57
71
  if isinstance(vault, AnsibleVaultEncryptedUnicode):
58
72
  vault.vault = vl
59
73
  data = vault.data
@@ -165,6 +165,9 @@ class LookupModule(LookupBase):
165
165
  total_search = []
166
166
  skip = False
167
167
 
168
+ if not terms and kwargs:
169
+ terms = ['']
170
+
168
171
  # can use a dict instead of list item to pass inline config
169
172
  for term in terms:
170
173
  if isinstance(term, Mapping):
@@ -509,8 +509,11 @@ class StrategyBase:
509
509
 
510
510
  def search_handlers_by_notification(self, notification: str, iterator: PlayIterator) -> t.Generator[Handler, None, None]:
511
511
  templar = Templar(None)
512
+ handlers = [h for b in reversed(iterator._play.handlers) for h in b.block]
512
513
  # iterate in reversed order since last handler loaded with the same name wins
513
- for handler in (h for b in reversed(iterator._play.handlers) for h in b.block if h.name):
514
+ for handler in handlers:
515
+ if not handler.name:
516
+ continue
514
517
  if not handler.cached_name:
515
518
  if templar.is_template(handler.name):
516
519
  templar.available_variables = self._variable_manager.get_vars(
@@ -548,7 +551,8 @@ class StrategyBase:
548
551
  break
549
552
 
550
553
  templar.available_variables = {}
551
- for handler in (h for b in iterator._play.handlers for h in b.block):
554
+ seen = []
555
+ for handler in handlers:
552
556
  if listeners := handler.listen:
553
557
  if notification in handler.get_validated_value(
554
558
  'listen',
@@ -556,6 +560,9 @@ class StrategyBase:
556
560
  listeners,
557
561
  templar,
558
562
  ):
563
+ if handler.name and handler.name in seen:
564
+ continue
565
+ seen.append(handler.name)
559
566
  yield handler
560
567
 
561
568
  @debug_closure
ansible/release.py CHANGED
@@ -19,6 +19,6 @@
19
19
  from __future__ import (absolute_import, division, print_function)
20
20
  __metaclass__ = type
21
21
 
22
- __version__ = '2.15.3rc1'
22
+ __version__ = '2.15.4'
23
23
  __author__ = 'Ansible, Inc.'
24
24
  __codename__ = "Ten Years Gone"
ansible/utils/display.py CHANGED
@@ -698,6 +698,8 @@ class Display(metaclass=Singleton):
698
698
  os.set_blocking(self._stdin_fd, False)
699
699
  while key_pressed is None and (seconds is None or (time.time() - start < seconds)):
700
700
  key_pressed = self._stdin.read(1)
701
+ # throttle to prevent excess CPU consumption
702
+ time.sleep(C.DEFAULT_INTERNAL_POLL_INTERVAL)
701
703
  finally:
702
704
  os.set_blocking(self._stdin_fd, True)
703
705
  if key_pressed is None:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ansible-core
3
- Version: 2.15.3rc1
3
+ Version: 2.15.4
4
4
  Summary: Radically simple IT automation
5
5
  Home-page: https://ansible.com/
6
6
  Author: Ansible, Inc.
@@ -3,7 +3,7 @@ ansible/__main__.py,sha256=IvyRvY64pT0on94qCLibxgDJ0-7_2CRoaZ5kfGOl54Q,1395
3
3
  ansible/constants.py,sha256=JLIDnuSz3_PbtXWsL4vnvVBbxlh3lSrJREd7T73atEI,8293
4
4
  ansible/context.py,sha256=OzSlaA_GgGRyyf5I209sy19_eGOX6HXn441W9w_FcvU,2018
5
5
  ansible/keyword_desc.yml,sha256=FYY0Ld1Xc3AxJ_Tefz78kRSYzIKGS8qcPtVk370J118,7367
6
- ansible/release.py,sha256=t2ZHMJZavg2xyqc2XUHGKOjrH28vpDOX6At_AxEU5-g,921
6
+ ansible/release.py,sha256=2duZFK1AVl1ss0RBbTx6863mXr1r9m60-qq_IlfpIYg,918
7
7
  ansible/_vendor/__init__.py,sha256=wJRKH7kI9OzYVY9hgSchOsTNTmTnugpPLGYj9Y5akX0,2086
8
8
  ansible/cli/__init__.py,sha256=ZK8bKuMmeRqeAcePriGtJ0tMuoDur3sN-ySBmOzAF3c,28687
9
9
  ansible/cli/adhoc.py,sha256=pGW6eysaireovp4sVsUuntg-l1o7DSujuhxVhVC2zsM,8230
@@ -57,7 +57,7 @@ ansible/executor/process/__init__.py,sha256=1lMXN1i2fFqslda4BmeI5tpYMFP95D5Wpr1A
57
57
  ansible/executor/process/worker.py,sha256=k5aTaoCUu_ZUmdnPgIGqGsD7013_o3srzwxNpAjD1SY,9415
58
58
  ansible/galaxy/__init__.py,sha256=_ccTedn8dUGGtkmHcQLIkeje_YD0TYSXlvCl1AOY5fE,2533
59
59
  ansible/galaxy/api.py,sha256=deSYsFinaJodT2Y9-XnOerWIwYY8V2AWQ_9kZI0pWCE,39872
60
- ansible/galaxy/role.py,sha256=roEhuloz2-UHLdNwK7pqRCYsOLpu_Xg6sC_nyE5A30w,19086
60
+ ansible/galaxy/role.py,sha256=h5ttpZ0VYY1c43l1S1tk3VKdLDF95ZcQAi9HtWw77ds,20337
61
61
  ansible/galaxy/token.py,sha256=K0dAwD3Fjkn3Zs2N9sG98UesSWfAukie47QGyYpIf0M,6167
62
62
  ansible/galaxy/user_agent.py,sha256=x7cJzzpnTngHcwqSUd2hg0i28Dv0tbAyBdke5CSiNhM,813
63
63
  ansible/galaxy/collection/__init__.py,sha256=othkH2m7kZYN5Q5e0boNP0rtr-fkjkiohjbYvUSWQHc,77429
@@ -140,9 +140,9 @@ ansible/inventory/host.py,sha256=wXJp6kpSaZtDr4JNsgdAuhi5MzQ9LTQzaAH10zoVbIA,505
140
140
  ansible/inventory/manager.py,sha256=tGwhBR6poLuG_i4jZ5RGOG-rH4gu4DBfT0-4iLLZZMs,29490
141
141
  ansible/module_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
142
142
  ansible/module_utils/_text.py,sha256=F_YfeaxhwmTI16HICAzQS9ZmlKgBDdQ4mqR-Kh--okg,597
143
- ansible/module_utils/ansible_release.py,sha256=t2ZHMJZavg2xyqc2XUHGKOjrH28vpDOX6At_AxEU5-g,921
143
+ ansible/module_utils/ansible_release.py,sha256=2duZFK1AVl1ss0RBbTx6863mXr1r9m60-qq_IlfpIYg,918
144
144
  ansible/module_utils/api.py,sha256=BTo7stVOANbtd-ngZslaqx70r9t5gfvo44cKyu5SFjU,5837
145
- ansible/module_utils/basic.py,sha256=KwFTKMws6bPfSEP1fIc7Srvan6b34EEbZ5nedfhhiTw,87493
145
+ ansible/module_utils/basic.py,sha256=EURZjMwQ_iCkR-QeFkEM9IwqjFKwWDoyzGOC7qehh28,88086
146
146
  ansible/module_utils/connection.py,sha256=XHxMlyAdwLiXDSo8jBMkV61-lz_0FDJUYH1B152UGJU,8430
147
147
  ansible/module_utils/errors.py,sha256=LYv9EWkvBRAmYW6qQY4Vz2hMULqkAGkMG2Opf86Ep4M,3396
148
148
  ansible/module_utils/json_utils.py,sha256=IR_bSwrYK1Ie36dCQSHyN4mahkrZkzIIkH3DdwtIi6Q,3456
@@ -180,11 +180,11 @@ ansible/module_utils/compat/selectors.py,sha256=WZCCn175Pyn-zDY7ep_xZqYrQpDfKpI8
180
180
  ansible/module_utils/compat/selinux.py,sha256=FDJE4H5flBECz6k11dI0BObuCZkhToAEcNrfBnw8aA8,3527
181
181
  ansible/module_utils/compat/typing.py,sha256=FRLIK2bdItKBR1xjYV9n3Jg-bqvT0-doekvjx0la6xk,780
182
182
  ansible/module_utils/compat/version.py,sha256=UKmpFhMk-Y9vuYfgmaT5NYctS3WFU-Xn9ycEzl01Nlc,12787
183
- ansible/module_utils/csharp/Ansible.AccessToken.cs,sha256=bGKFk92EEiG4omGPdUk3YZ_GzrDhzn0mO5yu_qC2rVs,16066
183
+ ansible/module_utils/csharp/Ansible.AccessToken.cs,sha256=4HzIFQKGG3ZTg8tehVcM_ukMi057wxxLdYFZoqsij5I,15871
184
184
  ansible/module_utils/csharp/Ansible.Basic.cs,sha256=slTfWp_cpHuxlzjSQMT5VMqIBKg8XE0Ynsa_w0WoX7Q,77734
185
- ansible/module_utils/csharp/Ansible.Become.cs,sha256=py7VKd4XjFahf8blwX_Zj5pUvVVCA547SaGDCpMJfME,30728
186
- ansible/module_utils/csharp/Ansible.Privilege.cs,sha256=xdreXzRqhvp2kpGWVqFrDrnZozb_JANVVhH_7MDZ4fw,19592
187
- ansible/module_utils/csharp/Ansible.Process.cs,sha256=YTTK2LNwxlUa1Xdvf3KER71JFyrZSyrsrZtEX5vkoqo,19568
185
+ ansible/module_utils/csharp/Ansible.Become.cs,sha256=1yasfX8SpbcIWJWiobr2Ms-Hl5W47_XNSKvwMXOyiz4,30457
186
+ ansible/module_utils/csharp/Ansible.Privilege.cs,sha256=7e46na6k6ygdRwN53bzfIS8O-IwfM1TF_q5DeFH2Z80,19398
187
+ ansible/module_utils/csharp/Ansible.Process.cs,sha256=g6R2PkbxiVBry4bk35ieWwYCAZOi7RSeyKmtOW8j90I,19449
188
188
  ansible/module_utils/csharp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
189
189
  ansible/module_utils/distro/__init__.py,sha256=UCWityXk2h5DRRwBgcvk2bO9jNY2kXfy14PS7TH8KVc,2026
190
190
  ansible/module_utils/distro/_distro.py,sha256=1T7OVSaUQD0ChjzYJL6NdbobB7tZy0M2NYcCGShjRXw,49344
@@ -381,7 +381,7 @@ ansible/playbook/notifiable.py,sha256=V6cvqy4H1Ti_kmTEw1YOgZOAulI9WgAAnfHeLOGyB5
381
381
  ansible/playbook/play.py,sha256=f9uTpi7o2bDoze8ZUFv5Iz3IAi06SISapW7e1YTko-U,16326
382
382
  ansible/playbook/play_context.py,sha256=j7v3B7frT874UOEWoW2uBSABstj5AyKuAf__U3fgN8A,14587
383
383
  ansible/playbook/playbook_include.py,sha256=sJiA8eGfaxMtNv4j3Gcf7OTy_mR37-tijxJ7p8IkEpI,7555
384
- ansible/playbook/role_include.py,sha256=AQaWxcilc1-T7wiKtpGANQN6emFLjMqpRiTCtSLnFo8,8046
384
+ ansible/playbook/role_include.py,sha256=6I9ELfnsZTsjCtbuVQj3FXnwpfvF6h4fAdar2JTP3Kc,8067
385
385
  ansible/playbook/taggable.py,sha256=7pCyNHhAs2TBTV6h4LT9gd9v2syY_gJZqg5x6p0w9C4,3169
386
386
  ansible/playbook/task.py,sha256=Fz3XKawh70CY-e4wLR8nu-ubkrigrTWfjV1nyfPgihQ,20145
387
387
  ansible/playbook/task_include.py,sha256=Qs6CpbwRcuyZeVaDGDclR5V-ZjZErncLpvmAGywRIro,6043
@@ -477,7 +477,7 @@ ansible/plugins/filter/core.py,sha256=e--btD-V9SrNpE5N8FeXgJR3l2za7JbKUdcQKstQjD
477
477
  ansible/plugins/filter/dict2items.yml,sha256=tUWJLVdZQ4sO0GYrJaC9wALSitTactFTdsrI9xb09KM,1314
478
478
  ansible/plugins/filter/difference.yml,sha256=a72tTaJswM3SS2NhFG2lQ5kRUnf5yYaouwS19f97bQA,1024
479
479
  ansible/plugins/filter/dirname.yml,sha256=Z7p7ay8s3_Zee6gIu7qr4wUC-an7lwLwuoVmgHQCKyg,820
480
- ansible/plugins/filter/encryption.py,sha256=dFznqIS2Q0XPnT-3yc77BHzF3sdfDXTVN_8AtfUdyCo,2693
480
+ ansible/plugins/filter/encryption.py,sha256=MaKN-e6yMWEaXMJktgp92OYNwUzptdza5DhOC5LcGtw,3307
481
481
  ansible/plugins/filter/expanduser.yml,sha256=P_AD4oBYbADe2f7pzHjbnkM95t8P1OzN0S3AHLT6C9o,506
482
482
  ansible/plugins/filter/expandvars.yml,sha256=KqtMP_oHLXsKFxHn_3iKX5PPGV5l-yhWX1jPD-sJOeE,569
483
483
  ansible/plugins/filter/extract.yml,sha256=Fcz4FJ2XfFux5bVb3sI48-PEGr8N0RsPM-VSKfbEEbE,1368
@@ -556,7 +556,7 @@ ansible/plugins/lookup/dict.py,sha256=44P9TxDwzxd5yTFP1VRf8KINCzikw6VmSEPGmpdSQw
556
556
  ansible/plugins/lookup/env.py,sha256=y0eaKInv6WDCgYw49huYjyw-GgDZ2nuo8jV7hNkuSGM,2731
557
557
  ansible/plugins/lookup/file.py,sha256=huVOrCviYDH730mYnB493lUEPY94759N0WaIYSjV2Sw,3201
558
558
  ansible/plugins/lookup/fileglob.py,sha256=03TDJRkCWdYntcjEpbow21JpJCaRYne6udJRBAb1JRI,2980
559
- ansible/plugins/lookup/first_found.py,sha256=u1AuLPxnAolQ-JStQ1ejNPKuqoVRTTcvKOtwPwOmNGg,8570
559
+ ansible/plugins/lookup/first_found.py,sha256=DlKEgq8lBXatpzvi-x9f44UTvr8KRKDbvVf6f4BSgRs,8629
560
560
  ansible/plugins/lookup/indexed_items.py,sha256=t3BqzGKKmnu3tZzFLwMISYpOBFgPLEJDJuS0Bbply8Q,1585
561
561
  ansible/plugins/lookup/ini.py,sha256=KKRqjC6fLf-i5-2Yp6a35IgeMyvO7S0RVE9Z7OUnvgQ,7779
562
562
  ansible/plugins/lookup/inventory_hostnames.py,sha256=MTVSpNwpDtJvR6Xyibuzi4jkJPv32xgTtah0VdaYVGY,1769
@@ -580,7 +580,7 @@ ansible/plugins/shell/__init__.py,sha256=Rj-H2AhfBZAWZ_Hy8D-1ypvjXTMP3pTbByOYlPM
580
580
  ansible/plugins/shell/cmd.py,sha256=fswLtU2XVNb1T5tF0BIM9msViObs5dXzo9k6sNN4dao,2207
581
581
  ansible/plugins/shell/powershell.py,sha256=qnpEZ9uOJF_4gExheFCAYT_tSR_KQtQeilU1WKXJymA,11376
582
582
  ansible/plugins/shell/sh.py,sha256=1nhiMv0_c8zu2MaDHvOCr--dG8b-iUVEPPnpMh_Hx8I,3952
583
- ansible/plugins/strategy/__init__.py,sha256=wK-vhOG-rRpuqys881CTZHnW_Jqs4_yeckw3pRoH0zg,57085
583
+ ansible/plugins/strategy/__init__.py,sha256=tS0fBmIcDcQn_kItveOh23BLaon9eudr0kmncMQPbEU,57275
584
584
  ansible/plugins/strategy/debug.py,sha256=GxUS0bSiaWInIK8zgB7rMREEqvgrZhVlFUzOCJtnjFo,1258
585
585
  ansible/plugins/strategy/free.py,sha256=eXAvxTFloyb5x6VYANXDMdloWUYxMhbPr1lyY6UPBps,15773
586
586
  ansible/plugins/strategy/host_pinned.py,sha256=3-q5l-tpheMlU-BXGm6ZQNgHvQv5IMvOCDZBLibl1L4,1959
@@ -649,7 +649,7 @@ ansible/utils/_junit_xml.py,sha256=zGOZeh7bKwASJ019TemgQtk-5j_eMC-exU6NKhSC7gI,8
649
649
  ansible/utils/cmd_functions.py,sha256=rh7_j2C93vVt-nueP9L2Ouz3Y_QAEQ7kI4dZTu2S6M4,2216
650
650
  ansible/utils/color.py,sha256=sBoONbLleSeCVPJMzyP4pvwSs1tKiSYwpCmAUq1Tzy0,4110
651
651
  ansible/utils/context_objects.py,sha256=1-j7SRLgVJU3J5b2PkXMcXS391z435SsKsYIU1m0eCw,3119
652
- ansible/utils/display.py,sha256=PPrbH_pIQwgHc_L22q0krzXR5aAxI4tv9BhvmDUJC_c,28192
652
+ ansible/utils/display.py,sha256=GXObgBX0WJfdxsiHN9wSOBdw9r-t9ARxhYe66UDIWwI,28322
653
653
  ansible/utils/encrypt.py,sha256=meEIayAAGzwa80zbW7LXmwxYl4hEjBxRudy8M52WS9I,10840
654
654
  ansible/utils/fqcn.py,sha256=bGTXbsj7wt0zfIf2c_mpLPTj8bGnjs1ACiRZAZpEs58,1268
655
655
  ansible/utils/galaxy.py,sha256=KkaFwPFCcn8S50R4jWDYzYm2H-2b95JUOxY2dAYPGIg,3914
@@ -682,7 +682,7 @@ ansible/vars/hostvars.py,sha256=dg3jpVmNwSg8EJ4SIvYGT80uxMgRtrOW6vvtDfrQzDU,5152
682
682
  ansible/vars/manager.py,sha256=qsF6PgAYcon5n7HmXG56P4pmKLyrniuFpAtKWnNaFpw,38284
683
683
  ansible/vars/plugins.py,sha256=B7L3fXoSOoBZSXqJ2ulk0adx1g5SpAb8BxyLGPNA7d4,4695
684
684
  ansible/vars/reserved.py,sha256=FBD7n2dnA0CW4I0J1LtWwk2hQqvGW0KTRPcxaRtMKWo,2615
685
- ansible_core-2.15.3rc1.data/scripts/ansible-test,sha256=CYIYL99IxWdVTtDIj3avilIJXhGAmtjuKPPWNuLWuc8,1690
685
+ ansible_core-2.15.4.data/scripts/ansible-test,sha256=CYIYL99IxWdVTtDIj3avilIJXhGAmtjuKPPWNuLWuc8,1690
686
686
  ansible_test/__init__.py,sha256=6e721yAyyyocRKzbCKtQXloAfFP7Aqv0L3zG70uh-4A,190
687
687
  ansible_test/_data/ansible.cfg,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
688
688
  ansible_test/_data/coveragerc,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -733,7 +733,7 @@ ansible_test/_data/requirements/sanity.yamllint.txt,sha256=rOXYavTA8af_3aGS1zU0D
733
733
  ansible_test/_data/requirements/units.txt,sha256=ah91xwwRFeY_fpi0WdRGw9GqEiAjm9BbVbnwTrdzn2g,125
734
734
  ansible_test/_data/requirements/windows-integration.txt,sha256=jx9vvE8tX1-sColj5E2WuDs1sZvhuqUJnqBjheSbP4U,65
735
735
  ansible_test/_internal/__init__.py,sha256=Ov_4Oh-B08xt4PU_7M_fMkmG9X9gnseBo78x0hmXZ98,3156
736
- ansible_test/_internal/ansible_util.py,sha256=6qb5I6GIjxoITHXwUm0QX9X6Y8ZSaEe_NyHFRUMmI9Q,10274
736
+ ansible_test/_internal/ansible_util.py,sha256=LpKPawaZObpfyUJZ018U5S5nIbQiMSsbj3JGQrTcfcU,12417
737
737
  ansible_test/_internal/become.py,sha256=zvOlaWKA4L6Cp6Xe795FsTw9xlWUy5Q5TicOwHXjzaI,3071
738
738
  ansible_test/_internal/bootstrap.py,sha256=UbkB1ZJ-2bs7qtwRRBi5516IsBq0vZl-pUoyrgzdROQ,2471
739
739
  ansible_test/_internal/cache.py,sha256=3W_1s5xdXdm-6Mhgrk1bNlr_Nde-B4FDN00LN0hVbfk,1050
@@ -741,13 +741,13 @@ ansible_test/_internal/cgroup.py,sha256=-7oLhkGrfCey8tt_4WNkJjeFRceBRK6EJXOmsRNX
741
741
  ansible_test/_internal/completion.py,sha256=BJvhJ0d6PhBBn28YwZ63iGKtTh5TQw6R_uPNMAnpETo,11026
742
742
  ansible_test/_internal/config.py,sha256=LJkfQ0d6EjEgRWoovdxQX1AK3TRSx-H_Cx1lneNPCEc,12524
743
743
  ansible_test/_internal/connections.py,sha256=-gK9FqvmpsjENdYNkvWgFgqYHJSS_F2XkvQzH2_s86E,7855
744
- ansible_test/_internal/constants.py,sha256=ON2eUuS1im4EzNrvfST5KiFUtun_GN8YgNjm06MzGG0,1969
744
+ ansible_test/_internal/constants.py,sha256=djMgWI_xR1Yg6M9Au8dEtao6yTYIzeLA-Ctxb1sKnHg,2056
745
745
  ansible_test/_internal/containers.py,sha256=YLRUYuLTUT4pSl7L9T_X1CI3lS53lBQk7lHQUwm5rX4,35635
746
746
  ansible_test/_internal/content_config.py,sha256=pkhIu5lg-o8oWc7RBzuniYE-mBPyjnf400vpaO0gr08,5778
747
747
  ansible_test/_internal/core_ci.py,sha256=qkOcmYldBC4EX3wvql5G29O8whPRzyTM00eUTRH-6e0,17594
748
748
  ansible_test/_internal/coverage_util.py,sha256=iw45rwz8Q5u37S4_dABNR0-Ybc5F8YRiEpUEKJiyjQ8,9302
749
749
  ansible_test/_internal/data.py,sha256=OFDpRa47yqBqQO1aSvTZVQQpScHvBHsr861586MQEUI,11184
750
- ansible_test/_internal/delegation.py,sha256=elCTCtsBtauVy0rE15BMC1EgUyfY5f8qusjWODiKKvw,13413
750
+ ansible_test/_internal/delegation.py,sha256=xw9pjUmdGLT-xz5LdcH4s4EMDFHrMrZeMv60Rkj7iDc,13458
751
751
  ansible_test/_internal/diff.py,sha256=COo6OgC3zxwymhOTlMifLZsGc1RGL0iM_zFVyqFNK48,7300
752
752
  ansible_test/_internal/docker_util.py,sha256=LF4RrClcsDhg3UqrqgOztbeB_oWcsf1nc3W4DFacans,37675
753
753
  ansible_test/_internal/encoding.py,sha256=E61EfXbQw0uQoFhbN3SYx3Oy_1tAMCPAAvY9hkEcSSo,1367
@@ -771,7 +771,7 @@ ansible_test/_internal/target.py,sha256=Whtb_n0jn4zbiMmX7je5jewgzsRczfXRm_ndYtjT
771
771
  ansible_test/_internal/test.py,sha256=znQmGjKACqDU8T0EAPqcv2qyy0J7M2w4OmyYhwHLqT0,14515
772
772
  ansible_test/_internal/thread.py,sha256=WQoZ2q2ljmEkKHRDkIqwxW7eZbkCKDrG3YZfcaxHzHw,2596
773
773
  ansible_test/_internal/timeout.py,sha256=hT-LirImhAh1iCGIh8JpmECXsiGu6Zetw8BWl1iBIC8,4050
774
- ansible_test/_internal/util.py,sha256=9F91OJLJBjtaG3CgFqCj7EqT0dnE9lKoj3LDO6FwaHc,37805
774
+ ansible_test/_internal/util.py,sha256=lLlIM2pQZqKIstrH2O5DkkIZ2R2QVYI_lRNehMaur7k,37683
775
775
  ansible_test/_internal/util_common.py,sha256=wxYutoQap6iemTLRC8c0fGSm3GP0ziAlq4XBV77aZfk,17389
776
776
  ansible_test/_internal/venv.py,sha256=DPHAt4tuoIdP7BOXa75-i4T7Paild8eGDsV2UUKOZ7U,9062
777
777
  ansible_test/_internal/ci/__init__.py,sha256=QOaC_8_wUzqFEbsFCXYAnElWoUo6gB40CXvP9RJ-Iyo,7738
@@ -862,17 +862,17 @@ ansible_test/_internal/commands/integration/cloud/vcenter.py,sha256=a1GALccb_wh1
862
862
  ansible_test/_internal/commands/integration/cloud/vultr.py,sha256=TE43tKiAerXbKD9FXBrBVzeWNUB87qtR5twg_zDicHM,1488
863
863
  ansible_test/_internal/commands/sanity/__init__.py,sha256=hP7MNOXoxclVsESt8JfLz85beEpx5W08dtgv5QDAJ_o,50352
864
864
  ansible_test/_internal/commands/sanity/ansible_doc.py,sha256=EY2PbiIAXkJRTS-WbTIirLDGaCwWZRJSnUIpViylHJA,5734
865
- ansible_test/_internal/commands/sanity/bin_symlinks.py,sha256=IAHze0HglLHnsUW4HowA8tmDzWGn4E8N5mnAi7hXPMI,3045
865
+ ansible_test/_internal/commands/sanity/bin_symlinks.py,sha256=uDiaMM3lf9KLlGTlGT53zYjgj6Fo-G-_dhJgFWnLS-o,3072
866
866
  ansible_test/_internal/commands/sanity/compile.py,sha256=ZQwHB85a7N6utr038kLbDZwFlXGEJMkSI63YyoGcd-I,2539
867
867
  ansible_test/_internal/commands/sanity/ignores.py,sha256=9wpzc8eRKS4nAVWOeSgXju5j1tDXNFPMSlskrR-Pohs,2789
868
868
  ansible_test/_internal/commands/sanity/import.py,sha256=gvPKZtJ4hyVclZmJsJcI4nxRqFRB8wGvJCmnUYEfF08,7571
869
869
  ansible_test/_internal/commands/sanity/integration_aliases.py,sha256=sGN5ATjW3_Xn0m_ncqxxFz8tLQ0jqpceHDaeIZzshMM,16221
870
- ansible_test/_internal/commands/sanity/mypy.py,sha256=nORKn27X6ePFs3qpWuSEmTS0bqNQ8jje-H8VNWsqgZE,10998
870
+ ansible_test/_internal/commands/sanity/mypy.py,sha256=4Vp5PVBSNMmWgSKxd2TjRQoeugCN8DRXscRNeKJwaLY,10982
871
871
  ansible_test/_internal/commands/sanity/pep8.py,sha256=SSulTIljaSu_exl93ZklKyuhbKS-zf18SKu23k3VJhA,3125
872
872
  ansible_test/_internal/commands/sanity/pslint.py,sha256=lVgL6RrDolRgIOJ2NRr04k2KVwMddZz1M7I-6h57vII,3210
873
873
  ansible_test/_internal/commands/sanity/pylint.py,sha256=8XxdckD4AVTkP8GamX6XaeGcMvYvf5yTgtUIN5d8aFk,10922
874
874
  ansible_test/_internal/commands/sanity/shellcheck.py,sha256=CZHNN_2iNVE3iqf5SIDSH9b2hwF6aXtJ0H6MPCEJX4s,3070
875
- ansible_test/_internal/commands/sanity/validate_modules.py,sha256=D4qXBfkWQ5NJam6TN9HOi_NWXEDErBFXatWoP-OiQjo,7904
875
+ ansible_test/_internal/commands/sanity/validate_modules.py,sha256=-NFR5xbp4DPaD-lW-JAwpI0dpGTQuMGnqjt4bxRERvU,8186
876
876
  ansible_test/_internal/commands/sanity/yamllint.py,sha256=rF_L-QVWLfQ5HiOf_Q-6AMdk7orOJN_Bu8XyMfobRQ8,3423
877
877
  ansible_test/_internal/commands/shell/__init__.py,sha256=70rahKppL1gi3I22YWZCkVKO9UF8Muryr0REiilb6C0,4371
878
878
  ansible_test/_internal/commands/units/__init__.py,sha256=eDwwBQ87zWaVLRQbQ7GBC8P8TUcu28bhIAZqIjDk1fY,12686
@@ -1001,9 +1001,9 @@ ansible_test/config/cloud-config-vultr.ini.template,sha256=XLKHk3lg_8ReQMdWfZzhh
1001
1001
  ansible_test/config/config.yml,sha256=wb3knoBmZewG3GWOMnRHoVPQWW4vPixKLPMNS6vJmTc,2620
1002
1002
  ansible_test/config/inventory.networking.template,sha256=bFNSk8zNQOaZ_twaflrY0XZ9mLwUbRLuNT0BdIFwvn4,1335
1003
1003
  ansible_test/config/inventory.winrm.template,sha256=1QU8W-GFLnYEw8yY9bVIvUAVvJYPM3hyoijf6-M7T00,1098
1004
- ansible_core-2.15.3rc1.dist-info/COPYING,sha256=CuBIWlvTemPmNgNZZBfk6w5lMzT6bH-TLKOg6F1K8ic,35148
1005
- ansible_core-2.15.3rc1.dist-info/METADATA,sha256=xlKbQJ-nQHLRYiAjtkJTukkTwNiidXagAVe6OjOPC-s,6978
1006
- ansible_core-2.15.3rc1.dist-info/WHEEL,sha256=5sUXSg9e4bi7lTLOHcm6QEYwO5TIF1TNbTSVFVjcJcc,92
1007
- ansible_core-2.15.3rc1.dist-info/entry_points.txt,sha256=0mpmsrIhODChxKl3eS-NcVQCaMetBn8KdPLtVxQgR64,453
1008
- ansible_core-2.15.3rc1.dist-info/top_level.txt,sha256=IFbRLjAvih1DYzJWg3_F6t4sCzEMxRO7TOMNs6GkYHo,21
1009
- ansible_core-2.15.3rc1.dist-info/RECORD,,
1004
+ ansible_core-2.15.4.dist-info/COPYING,sha256=CuBIWlvTemPmNgNZZBfk6w5lMzT6bH-TLKOg6F1K8ic,35148
1005
+ ansible_core-2.15.4.dist-info/METADATA,sha256=AfuGfdFKqoNaqCcCLcxoGhiH4KyEVgH-_FaANGy7tgA,6975
1006
+ ansible_core-2.15.4.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
1007
+ ansible_core-2.15.4.dist-info/entry_points.txt,sha256=0mpmsrIhODChxKl3eS-NcVQCaMetBn8KdPLtVxQgR64,453
1008
+ ansible_core-2.15.4.dist-info/top_level.txt,sha256=IFbRLjAvih1DYzJWg3_F6t4sCzEMxRO7TOMNs6GkYHo,21
1009
+ ansible_core-2.15.4.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.41.1)
2
+ Generator: bdist_wheel (0.41.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -3,9 +3,11 @@ from __future__ import annotations
3
3
 
4
4
  import json
5
5
  import os
6
+ import shutil
6
7
  import typing as t
7
8
 
8
9
  from .constants import (
10
+ ANSIBLE_BIN_SYMLINK_MAP,
9
11
  SOFT_RLIMIT_NOFILE,
10
12
  )
11
13
 
@@ -17,12 +19,15 @@ from .util import (
17
19
  common_environment,
18
20
  ApplicationError,
19
21
  ANSIBLE_LIB_ROOT,
22
+ ANSIBLE_TEST_ROOT,
20
23
  ANSIBLE_TEST_DATA_ROOT,
21
- ANSIBLE_BIN_PATH,
24
+ ANSIBLE_ROOT,
22
25
  ANSIBLE_SOURCE_ROOT,
23
26
  ANSIBLE_TEST_TOOLS_ROOT,
27
+ MODE_FILE_EXECUTE,
24
28
  get_ansible_version,
25
29
  raw_command,
30
+ verified_chmod,
26
31
  )
27
32
 
28
33
  from .util_common import (
@@ -78,8 +83,10 @@ def ansible_environment(args: CommonConfig, color: bool = True, ansible_config:
78
83
  env = common_environment()
79
84
  path = env['PATH']
80
85
 
81
- if not path.startswith(ANSIBLE_BIN_PATH + os.path.pathsep):
82
- path = ANSIBLE_BIN_PATH + os.path.pathsep + path
86
+ ansible_bin_path = get_ansible_bin_path(args)
87
+
88
+ if not path.startswith(ansible_bin_path + os.path.pathsep):
89
+ path = ansible_bin_path + os.path.pathsep + path
83
90
 
84
91
  if not ansible_config:
85
92
  # use the default empty configuration unless one has been provided
@@ -196,6 +203,52 @@ def configure_plugin_paths(args: CommonConfig) -> dict[str, str]:
196
203
  return env
197
204
 
198
205
 
206
+ @mutex
207
+ def get_ansible_bin_path(args: CommonConfig) -> str:
208
+ """
209
+ Return a directory usable for PATH, containing only the ansible entry points.
210
+ If a temporary directory is required, it will be cached for the lifetime of the process and cleaned up at exit.
211
+ """
212
+ try:
213
+ return get_ansible_bin_path.bin_path # type: ignore[attr-defined]
214
+ except AttributeError:
215
+ pass
216
+
217
+ if ANSIBLE_SOURCE_ROOT:
218
+ # when running from source there is no need for a temporary directory since we already have known entry point scripts
219
+ bin_path = os.path.join(ANSIBLE_ROOT, 'bin')
220
+ else:
221
+ # when not running from source the installed entry points cannot be relied upon
222
+ # doing so would require using the interpreter specified by those entry points, which conflicts with using our interpreter and injector
223
+ # instead a temporary directory is created which contains only ansible entry points
224
+ # symbolic links cannot be used since the files are likely not executable
225
+ bin_path = create_temp_dir(prefix='ansible-test-', suffix='-bin')
226
+ bin_links = {os.path.join(bin_path, name): get_cli_path(path) for name, path in ANSIBLE_BIN_SYMLINK_MAP.items()}
227
+
228
+ if not args.explain:
229
+ for dst, src in bin_links.items():
230
+ shutil.copy(src, dst)
231
+ verified_chmod(dst, MODE_FILE_EXECUTE)
232
+
233
+ get_ansible_bin_path.bin_path = bin_path # type: ignore[attr-defined]
234
+
235
+ return bin_path
236
+
237
+
238
+ def get_cli_path(path: str) -> str:
239
+ """Return the absolute path to the CLI script from the given path which is relative to the `bin` directory of the original source tree layout."""
240
+ path_rewrite = {
241
+ '../lib/ansible/': ANSIBLE_LIB_ROOT,
242
+ '../test/lib/ansible_test/': ANSIBLE_TEST_ROOT,
243
+ }
244
+
245
+ for prefix, destination in path_rewrite.items():
246
+ if path.startswith(prefix):
247
+ return os.path.join(destination, path[len(prefix):])
248
+
249
+ raise RuntimeError(path)
250
+
251
+
199
252
  @mutex
200
253
  def get_ansible_python_path(args: CommonConfig) -> str:
201
254
  """
@@ -32,7 +32,7 @@ from ...payload import (
32
32
  )
33
33
 
34
34
  from ...util import (
35
- ANSIBLE_BIN_PATH,
35
+ ANSIBLE_SOURCE_ROOT,
36
36
  )
37
37
 
38
38
 
@@ -52,7 +52,7 @@ class BinSymlinksTest(SanityVersionNeutral):
52
52
  return True
53
53
 
54
54
  def test(self, args: SanityConfig, targets: SanityTargets) -> TestResult:
55
- bin_root = ANSIBLE_BIN_PATH
55
+ bin_root = os.path.join(ANSIBLE_SOURCE_ROOT, 'bin')
56
56
  bin_names = os.listdir(bin_root)
57
57
  bin_paths = sorted(os.path.join(bin_root, path) for path in bin_names)
58
58
 
@@ -73,7 +73,7 @@ class MypyTest(SanityMultipleVersion):
73
73
  """Return the given list of test targets, filtered to include only those relevant for the test."""
74
74
  return [target for target in targets if os.path.splitext(target.path)[1] == '.py' and target.path not in self.vendored_paths and (
75
75
  target.path.startswith('lib/ansible/') or target.path.startswith('test/lib/ansible_test/_internal/')
76
- or target.path.startswith('packaging/cli-doc/')
76
+ or target.path.startswith('packaging/')
77
77
  or target.path.startswith('test/lib/ansible_test/_util/target/sanity/import/'))]
78
78
 
79
79
  @property
@@ -117,7 +117,7 @@ class MypyTest(SanityMultipleVersion):
117
117
  MyPyContext('ansible-test', ['test/lib/ansible_test/_internal/'], controller_python_versions),
118
118
  MyPyContext('ansible-core', ['lib/ansible/'], controller_python_versions),
119
119
  MyPyContext('modules', ['lib/ansible/modules/', 'lib/ansible/module_utils/'], remote_only_python_versions),
120
- MyPyContext('packaging', ['packaging/cli-doc/'], controller_python_versions),
120
+ MyPyContext('packaging', ['packaging/'], controller_python_versions),
121
121
  )
122
122
 
123
123
  unfiltered_messages: list[SanityMessage] = []
@@ -159,7 +159,11 @@ class ValidateModulesTest(SanitySingleVersion):
159
159
  temp_dir = process_scoped_temporary_directory(args)
160
160
 
161
161
  with tarfile.open(path) as file:
162
- file.extractall(temp_dir)
162
+ # deprecated: description='extractall fallback without filter' python_version='3.11'
163
+ if hasattr(tarfile, 'data_filter'):
164
+ file.extractall(temp_dir, filter='data') # type: ignore[call-arg]
165
+ else:
166
+ file.extractall(temp_dir)
163
167
 
164
168
  cmd.extend([
165
169
  '--original-plugins', temp_dir,
@@ -33,6 +33,7 @@ SECCOMP_CHOICES = [
33
33
  # This bin symlink map must exactly match the contents of the bin directory.
34
34
  # It is necessary for payload creation to reconstruct the bin directory when running ansible-test from an installed version of ansible.
35
35
  # It is also used to construct the injector directory at runtime.
36
+ # It is also used to construct entry points when not running ansible-test from source.
36
37
  ANSIBLE_BIN_SYMLINK_MAP = {
37
38
  'ansible': '../lib/ansible/cli/adhoc.py',
38
39
  'ansible-config': '../lib/ansible/cli/config.py',
@@ -33,7 +33,6 @@ from .util import (
33
33
  SubprocessError,
34
34
  display,
35
35
  filter_args,
36
- ANSIBLE_BIN_PATH,
37
36
  ANSIBLE_LIB_ROOT,
38
37
  ANSIBLE_TEST_ROOT,
39
38
  OutputStream,
@@ -44,6 +43,10 @@ from .util_common import (
44
43
  process_scoped_temporary_directory,
45
44
  )
46
45
 
46
+ from .ansible_util import (
47
+ get_ansible_bin_path,
48
+ )
49
+
47
50
  from .containers import (
48
51
  support_container_context,
49
52
  ContainerDatabase,
@@ -145,7 +148,7 @@ def delegate_command(args: EnvironmentConfig, host_state: HostState, exclude: li
145
148
  con.extract_archive(chdir=working_directory, src=payload_file)
146
149
  else:
147
150
  content_root = working_directory
148
- ansible_bin_path = ANSIBLE_BIN_PATH
151
+ ansible_bin_path = get_ansible_bin_path(args)
149
152
 
150
153
  command = generate_command(args, host_state.controller_profile.python, ansible_bin_path, content_root, exclude, require)
151
154
 
@@ -74,14 +74,12 @@ ANSIBLE_TEST_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
74
74
 
75
75
  # assume running from install
76
76
  ANSIBLE_ROOT = os.path.dirname(ANSIBLE_TEST_ROOT)
77
- ANSIBLE_BIN_PATH = os.path.dirname(os.path.abspath(sys.argv[0]))
78
77
  ANSIBLE_LIB_ROOT = os.path.join(ANSIBLE_ROOT, 'ansible')
79
78
  ANSIBLE_SOURCE_ROOT = None
80
79
 
81
80
  if not os.path.exists(ANSIBLE_LIB_ROOT):
82
81
  # running from source
83
82
  ANSIBLE_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(ANSIBLE_TEST_ROOT)))
84
- ANSIBLE_BIN_PATH = os.path.join(ANSIBLE_ROOT, 'bin')
85
83
  ANSIBLE_LIB_ROOT = os.path.join(ANSIBLE_ROOT, 'lib', 'ansible')
86
84
  ANSIBLE_SOURCE_ROOT = ANSIBLE_ROOT
87
85