ansible-core 2.17.3rc1__py3-none-any.whl → 2.17.4rc1__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.

ansible/config/base.yml CHANGED
@@ -948,7 +948,7 @@ DEFAULT_PRIVATE_ROLE_VARS:
948
948
  - This was introduced as a way to reset role variables to default values if a role is used more than once
949
949
  in a playbook.
950
950
  - Starting in version '2.17' M(ansible.builtin.include_roles) and M(ansible.builtin.import_roles) can
951
- indivudually override this via the C(public) parameter.
951
+ individually override this via the C(public) parameter.
952
952
  - Included roles only make their variables public at execution, unlike imported roles which happen at playbook compile time.
953
953
  env: [{name: ANSIBLE_PRIVATE_ROLE_VARS}]
954
954
  ini:
@@ -31,7 +31,7 @@ from ansible.utils.listify import listify_lookup_plugin_terms
31
31
  from ansible.utils.unsafe_proxy import to_unsafe_text, wrap_var
32
32
  from ansible.vars.clean import namespace_facts, clean_facts
33
33
  from ansible.utils.display import Display
34
- from ansible.utils.vars import combine_vars, isidentifier
34
+ from ansible.utils.vars import combine_vars
35
35
 
36
36
  display = Display()
37
37
 
@@ -332,6 +332,13 @@ class TaskExecutor:
332
332
  (self._task, tmp_task) = (tmp_task, self._task)
333
333
  (self._play_context, tmp_play_context) = (tmp_play_context, self._play_context)
334
334
  res = self._execute(variables=task_vars)
335
+
336
+ if self._task.register:
337
+ # Ensure per loop iteration results are registered in case `_execute()`
338
+ # returns early (when conditional, failure, ...).
339
+ # This is needed in case the registered variable is used in the loop label template.
340
+ task_vars[self._task.register] = res
341
+
335
342
  task_fields = self._task.dump_attrs()
336
343
  (self._task, tmp_task) = (tmp_task, self._task)
337
344
  (self._play_context, tmp_play_context) = (tmp_play_context, self._play_context)
@@ -657,9 +664,6 @@ class TaskExecutor:
657
664
  # update the local copy of vars with the registered value, if specified,
658
665
  # or any facts which may have been generated by the module execution
659
666
  if self._task.register:
660
- if not isidentifier(self._task.register):
661
- raise AnsibleError("Invalid variable name in 'register' specified: '%s'" % self._task.register)
662
-
663
667
  vars_copy[self._task.register] = result
664
668
 
665
669
  if self._task.async_val > 0:
@@ -1048,7 +1052,7 @@ class TaskExecutor:
1048
1052
  # add extras if plugin supports them
1049
1053
  if getattr(self._connection, 'allow_extras', False):
1050
1054
  for k in variables:
1051
- if k.startswith('ansible_%s_' % self._connection._load_name) and k not in options:
1055
+ if k.startswith('ansible_%s_' % self._connection.extras_prefix) and k not in options:
1052
1056
  options['_extras'][k] = templar.template(variables[k])
1053
1057
 
1054
1058
  task_keys = self._task.dump_attrs()
@@ -17,6 +17,6 @@
17
17
 
18
18
  from __future__ import annotations
19
19
 
20
- __version__ = '2.17.3rc1'
20
+ __version__ = '2.17.4rc1'
21
21
  __author__ = 'Ansible, Inc.'
22
22
  __codename__ = "Gallows Pole"
@@ -1686,8 +1686,12 @@ class AnsibleModule(object):
1686
1686
  umask = os.umask(0)
1687
1687
  os.umask(umask)
1688
1688
  os.chmod(b_dest, S_IRWU_RWG_RWO & ~umask)
1689
+ dest_dir_stat = os.stat(os.path.dirname(b_dest))
1689
1690
  try:
1690
- os.chown(b_dest, os.geteuid(), os.getegid())
1691
+ if dest_dir_stat.st_mode & stat.S_ISGID:
1692
+ os.chown(b_dest, os.geteuid(), dest_dir_stat.st_gid)
1693
+ else:
1694
+ os.chown(b_dest, os.geteuid(), os.getegid())
1691
1695
  except OSError:
1692
1696
  # We're okay with trying our best here. If the user is not
1693
1697
  # root (or old Unices) they won't be able to chown.
@@ -329,11 +329,10 @@ class DataLoader:
329
329
  if (is_role or self._is_role(path)) and b_pb_base_dir.endswith(b'/tasks'):
330
330
  search.append(os.path.join(os.path.dirname(b_pb_base_dir), b_dirname, b_source))
331
331
  search.append(os.path.join(b_pb_base_dir, b_source))
332
- else:
333
- # don't add dirname if user already is using it in source
334
- if b_source.split(b'/')[0] != dirname:
335
- search.append(os.path.join(b_upath, b_dirname, b_source))
336
- search.append(os.path.join(b_upath, b_source))
332
+ # don't add dirname if user already is using it in source
333
+ if b_source.split(b'/')[0] != dirname:
334
+ search.append(os.path.join(b_upath, b_dirname, b_source))
335
+ search.append(os.path.join(b_upath, b_source))
337
336
 
338
337
  # always append basedir as last resort
339
338
  # don't add dirname if user already is using it in source
ansible/playbook/task.py CHANGED
@@ -37,6 +37,7 @@ from ansible.playbook.taggable import Taggable
37
37
  from ansible.utils.collection_loader import AnsibleCollectionConfig
38
38
  from ansible.utils.display import Display
39
39
  from ansible.utils.sentinel import Sentinel
40
+ from ansible.utils.vars import isidentifier
40
41
 
41
42
  __all__ = ['Task']
42
43
 
@@ -274,6 +275,10 @@ class Task(Base, Conditional, Taggable, CollectionSearch, Notifiable, Delegatabl
274
275
  if not isinstance(value, list):
275
276
  setattr(self, name, [value])
276
277
 
278
+ def _validate_register(self, attr, name, value):
279
+ if value is not None and not isidentifier(value):
280
+ raise AnsibleParserError(f"Invalid variable name in 'register' specified: '{value}'")
281
+
277
282
  def post_validate(self, templar):
278
283
  '''
279
284
  Override of base class post_validate, to also do final validation on
@@ -74,7 +74,7 @@ class TaskInclude(Task):
74
74
  if not task.args.get('_raw_params'):
75
75
  task.args['_raw_params'] = task.args.pop('file', None)
76
76
  if not task.args['_raw_params']:
77
- raise AnsibleParserError('No file specified for %s' % task.action)
77
+ raise AnsibleParserError('No file specified for %s' % task.action, obj=data)
78
78
 
79
79
  apply_attrs = task.args.get('apply', {})
80
80
  if apply_attrs and task.action not in C._ACTION_INCLUDE_TASKS:
@@ -50,16 +50,23 @@ def get_plugin_class(obj):
50
50
 
51
51
  class AnsiblePlugin(ABC):
52
52
 
53
- # allow extra passthrough parameters
54
- allow_extras = False
55
-
56
53
  # Set by plugin loader
57
54
  _load_name: str
58
55
 
56
+ # allow extra passthrough parameters
57
+ allow_extras: bool = False
58
+ _extras_prefix: str | None = None
59
+
59
60
  def __init__(self):
60
61
  self._options = {}
61
62
  self._defs = None
62
63
 
64
+ @property
65
+ def extras_prefix(self):
66
+ if not self._extras_prefix:
67
+ self._extras_prefix = self._load_name.split('.')[-1]
68
+ return self._extras_prefix
69
+
63
70
  def matches_name(self, possible_names):
64
71
  possible_fqcns = set()
65
72
  for name in possible_names:
@@ -632,39 +632,41 @@ end {
632
632
  buffer_size = max_b64_size - (max_b64_size % 1024)
633
633
 
634
634
  # setup the file stream with read only mode
635
- setup_script = '''$ErrorActionPreference = "Stop"
636
- $path = '%s'
635
+ setup_script = '''param([string]$Path)
636
+ $ErrorActionPreference = "Stop"
637
637
 
638
- if (Test-Path -Path $path -PathType Leaf) {
638
+ if (Test-Path -LiteralPath $path -PathType Leaf) {
639
639
  $fs = New-Object -TypeName System.IO.FileStream -ArgumentList @(
640
640
  $path,
641
641
  [System.IO.FileMode]::Open,
642
642
  [System.IO.FileAccess]::Read,
643
643
  [System.IO.FileShare]::Read
644
644
  )
645
- $buffer_size = %d
646
645
  } elseif (Test-Path -Path $path -PathType Container) {
647
646
  Write-Output -InputObject "[DIR]"
648
647
  } else {
649
648
  Write-Error -Message "$path does not exist"
650
649
  $host.SetShouldExit(1)
651
- }''' % (self._shell._escape(in_path), buffer_size)
650
+ }'''
652
651
 
653
652
  # read the file stream at the offset and return the b64 string
654
- read_script = '''$ErrorActionPreference = "Stop"
655
- $fs.Seek(%d, [System.IO.SeekOrigin]::Begin) > $null
656
- $buffer = New-Object -TypeName byte[] -ArgumentList $buffer_size
657
- $bytes_read = $fs.Read($buffer, 0, $buffer_size)
658
-
659
- if ($bytes_read -gt 0) {
660
- $bytes = $buffer[0..($bytes_read - 1)]
661
- Write-Output -InputObject ([System.Convert]::ToBase64String($bytes))
653
+ read_script = '''param([int64]$Offset, [int]$BufferSize)
654
+ $ErrorActionPreference = "Stop"
655
+ $fs.Seek($Offset, [System.IO.SeekOrigin]::Begin) > $null
656
+ $buffer = New-Object -TypeName byte[] -ArgumentList $BufferSize
657
+ $read = $fs.Read($buffer, 0, $buffer.Length)
658
+
659
+ if ($read -gt 0) {
660
+ [System.Convert]::ToBase64String($buffer, 0, $read)
662
661
  }'''
663
662
 
664
663
  # need to run the setup script outside of the local scope so the
665
664
  # file stream stays active between fetch operations
666
- rc, stdout, stderr = self._exec_psrp_script(setup_script,
667
- use_local_scope=False)
665
+ rc, stdout, stderr = self._exec_psrp_script(
666
+ setup_script,
667
+ use_local_scope=False,
668
+ arguments=[in_path],
669
+ )
668
670
  if rc != 0:
669
671
  raise AnsibleError("failed to setup file stream for fetch '%s': %s"
670
672
  % (out_path, to_native(stderr)))
@@ -679,7 +681,10 @@ if ($bytes_read -gt 0) {
679
681
  while True:
680
682
  display.vvvvv("PSRP FETCH %s to %s (offset=%d" %
681
683
  (in_path, out_path, offset), host=self._psrp_host)
682
- rc, stdout, stderr = self._exec_psrp_script(read_script % offset)
684
+ rc, stdout, stderr = self._exec_psrp_script(
685
+ read_script,
686
+ arguments=[offset, buffer_size],
687
+ )
683
688
  if rc != 0:
684
689
  raise AnsibleError("failed to transfer file to '%s': %s"
685
690
  % (out_path, to_native(stderr)))
@@ -813,7 +818,7 @@ if ($bytes_read -gt 0) {
813
818
  script: str,
814
819
  input_data: bytes | str | t.Iterable | None = None,
815
820
  use_local_scope: bool = True,
816
- arguments: t.Iterable[str] | None = None,
821
+ arguments: t.Iterable[t.Any] | None = None,
817
822
  ) -> tuple[int, bytes, bytes]:
818
823
  # Check if there's a command on the current pipeline that still needs to be closed.
819
824
  if self._last_pipeline:
@@ -1250,7 +1250,7 @@ class Connection(ConnectionBase):
1250
1250
  if sftp_action == 'get':
1251
1251
  # we pass sudoable=False to disable pty allocation, which
1252
1252
  # would end up mixing stdout/stderr and screwing with newlines
1253
- (returncode, stdout, stderr) = self.exec_command('dd if=%s bs=%s' % (in_path, BUFSIZE), sudoable=False)
1253
+ (returncode, stdout, stderr) = self.exec_command('dd if=%s bs=%s' % (self._shell.quote(in_path), BUFSIZE), sudoable=False)
1254
1254
  with open(to_bytes(out_path, errors='surrogate_or_strict'), 'wb+') as out_file:
1255
1255
  out_file.write(stdout)
1256
1256
  else:
@@ -12,6 +12,7 @@ DOCUMENTATION = r"""
12
12
  - The csvfile lookup reads the contents of a file in CSV (comma-separated value) format.
13
13
  The lookup looks for the row where the first column matches keyname (which can be multiple words)
14
14
  and returns the value in the O(col) column (default 1, which indexed from 0 means the second column in the file).
15
+ - At least one keyname is required, provided as a positional argument(s) to the lookup.
15
16
  options:
16
17
  col:
17
18
  description: column to return (0 indexed).
@@ -63,6 +64,22 @@ EXAMPLES = """
63
64
  vars:
64
65
  csvline: "{{ lookup('ansible.builtin.csvfile', bgp_neighbor_ip, file='bgp_neighbors.csv', delimiter=',') }}"
65
66
  delegate_to: localhost
67
+
68
+ # Contents of debug.csv
69
+ # test1 ret1.1 ret2.1
70
+ # test2 ret1.2 ret2.2
71
+ # test3 ret1.3 ret2.3
72
+
73
+ - name: "Lookup multiple keynames in the first column (index 0), returning the values from the second column (index 1)"
74
+ debug:
75
+ msg: "{{ lookup('csvfile', 'test1', 'test2', file='debug.csv', delimiter=' ') }}"
76
+
77
+ - name: Lookup multiple keynames using old style syntax
78
+ debug:
79
+ msg: "{{ lookup('csvfile', term1, term2) }}"
80
+ vars:
81
+ term1: "test1 file=debug.csv delimiter=' '"
82
+ term2: "test2 file=debug.csv delimiter=' '"
66
83
  """
67
84
 
68
85
  RETURN = """
@@ -150,6 +167,9 @@ class LookupModule(LookupBase):
150
167
  # populate options
151
168
  paramvals = self.get_options()
152
169
 
170
+ if not terms:
171
+ raise AnsibleError('Search key is required but was not found')
172
+
153
173
  for term in terms:
154
174
  kv = parse_kv(term)
155
175
 
@@ -25,35 +25,70 @@ import ntpath
25
25
  from ansible.module_utils.common.text.converters import to_bytes, to_text
26
26
  from ansible.plugins.shell import ShellBase
27
27
 
28
+ # This is weird, we are matching on byte sequences that match the utf-16-be
29
+ # matches for '_x(a-fA-F0-9){4}_'. The \x00 and {8} will match the hex sequence
30
+ # when it is encoded as utf-16-be.
31
+ _STRING_DESERIAL_FIND = re.compile(rb"\x00_\x00x([\x00(a-fA-F0-9)]{8})\x00_")
28
32
 
29
33
  _common_args = ['PowerShell', '-NoProfile', '-NonInteractive', '-ExecutionPolicy', 'Unrestricted']
30
34
 
31
35
 
32
- def _parse_clixml(data, stream="Error"):
36
+ def _parse_clixml(data: bytes, stream: str = "Error") -> bytes:
33
37
  """
34
38
  Takes a byte string like '#< CLIXML\r\n<Objs...' and extracts the stream
35
39
  message encoded in the XML data. CLIXML is used by PowerShell to encode
36
40
  multiple objects in stderr.
37
41
  """
38
- lines = []
42
+ lines: list[str] = []
43
+
44
+ # A serialized string will serialize control chars and surrogate pairs as
45
+ # _xDDDD_ values where DDDD is the hex representation of a big endian
46
+ # UTF-16 code unit. As a surrogate pair uses 2 UTF-16 code units, we need
47
+ # to operate our text replacement on the utf-16-be byte encoding of the raw
48
+ # text. This allows us to replace the _xDDDD_ values with the actual byte
49
+ # values and then decode that back to a string from the utf-16-be bytes.
50
+ def rplcr(matchobj: re.Match) -> bytes:
51
+ match_hex = matchobj.group(1)
52
+ hex_string = match_hex.decode("utf-16-be")
53
+ return base64.b16decode(hex_string.upper())
39
54
 
40
55
  # There are some scenarios where the stderr contains a nested CLIXML element like
41
56
  # '<# CLIXML\r\n<# CLIXML\r\n<Objs>...</Objs><Objs>...</Objs>'.
42
57
  # Parse each individual <Objs> element and add the error strings to our stderr list.
43
58
  # https://github.com/ansible/ansible/issues/69550
44
59
  while data:
45
- end_idx = data.find(b"</Objs>") + 7
46
- current_element = data[data.find(b"<Objs "):end_idx]
60
+ start_idx = data.find(b"<Objs ")
61
+ end_idx = data.find(b"</Objs>")
62
+ if start_idx == -1 or end_idx == -1:
63
+ break
64
+
65
+ end_idx += 7
66
+ current_element = data[start_idx:end_idx]
47
67
  data = data[end_idx:]
48
68
 
49
69
  clixml = ET.fromstring(current_element)
50
70
  namespace_match = re.match(r'{(.*)}', clixml.tag)
51
- namespace = "{%s}" % namespace_match.group(1) if namespace_match else ""
71
+ namespace = f"{{{namespace_match.group(1)}}}" if namespace_match else ""
72
+
73
+ entries = clixml.findall("./%sS" % namespace)
74
+ if not entries:
75
+ continue
76
+
77
+ # If this is a new CLIXML element, add a newline to separate the messages.
78
+ if lines:
79
+ lines.append("\r\n")
80
+
81
+ for string_entry in entries:
82
+ actual_stream = string_entry.attrib.get('S', None)
83
+ if actual_stream != stream:
84
+ continue
85
+
86
+ b_line = (string_entry.text or "").encode("utf-16-be")
87
+ b_escaped = re.sub(_STRING_DESERIAL_FIND, rplcr, b_line)
52
88
 
53
- strings = clixml.findall("./%sS" % namespace)
54
- lines.extend([e.text.replace('_x000D__x000A_', '') for e in strings if e.attrib.get('S') == stream])
89
+ lines.append(b_escaped.decode("utf-16-be", errors="surrogatepass"))
55
90
 
56
- return to_bytes('\r\n'.join(lines))
91
+ return to_bytes(''.join(lines), errors="surrogatepass")
57
92
 
58
93
 
59
94
  class ShellModule(ShellBase):
@@ -54,7 +54,7 @@ from ansible.utils.display import Display
54
54
  from ansible.utils.fqcn import add_internal_fqcns
55
55
  from ansible.utils.unsafe_proxy import wrap_var
56
56
  from ansible.utils.sentinel import Sentinel
57
- from ansible.utils.vars import combine_vars, isidentifier
57
+ from ansible.utils.vars import combine_vars
58
58
  from ansible.vars.clean import strip_internal_keys, module_response_deepcopy
59
59
 
60
60
  display = Display()
@@ -766,10 +766,6 @@ class StrategyBase:
766
766
 
767
767
  # register final results
768
768
  if original_task.register:
769
-
770
- if not isidentifier(original_task.register):
771
- raise AnsibleError("Invalid variable name in 'register' specified: '%s'" % original_task.register)
772
-
773
769
  host_list = self.get_task_hosts(iterator, original_host, original_task)
774
770
 
775
771
  clean_copy = strip_internal_keys(module_response_deepcopy(task_result._result))
@@ -95,6 +95,7 @@ class StrategyModule(StrategyBase):
95
95
 
96
96
  # try and find an unblocked host with a task to run
97
97
  host_results = []
98
+ meta_task_dummy_results_count = 0
98
99
  while True:
99
100
  host = hosts_left[last_host]
100
101
  display.debug("next free host: %s" % host)
@@ -181,6 +182,9 @@ class StrategyModule(StrategyBase):
181
182
  continue
182
183
 
183
184
  if task.action in C._ACTION_META:
185
+ if self._host_pinned:
186
+ meta_task_dummy_results_count += 1
187
+ workers_free -= 1
184
188
  self._execute_meta(task, play_context, iterator, target_host=host)
185
189
  self._blocked_hosts[host_name] = False
186
190
  else:
@@ -220,7 +224,7 @@ class StrategyModule(StrategyBase):
220
224
  host_results.extend(results)
221
225
 
222
226
  # each result is counted as a worker being free again
223
- workers_free += len(results)
227
+ workers_free += len(results) + meta_task_dummy_results_count
224
228
 
225
229
  self.update_active_connections(results)
226
230
 
ansible/release.py CHANGED
@@ -17,6 +17,6 @@
17
17
 
18
18
  from __future__ import annotations
19
19
 
20
- __version__ = '2.17.3rc1'
20
+ __version__ = '2.17.4rc1'
21
21
  __author__ = 'Ansible, Inc.'
22
22
  __codename__ = "Gallows Pole"
ansible/utils/version.py CHANGED
@@ -190,6 +190,7 @@ class SemanticVersion(Version):
190
190
  raise ValueError("invalid semantic version '%s'" % vstring)
191
191
 
192
192
  (major, minor, patch, prerelease, buildmetadata) = match.group(1, 2, 3, 4, 5)
193
+ self.vstring = vstring
193
194
  self.major = int(major)
194
195
  self.minor = int(minor)
195
196
  self.patch = int(patch)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ansible-core
3
- Version: 2.17.3rc1
3
+ Version: 2.17.4rc1
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=EnLcULXNtSXkuJ8igEHPPLBTZKAwqXv4PvMEhvzp2Oo,1430
3
3
  ansible/constants.py,sha256=vRwEcoynqtuKDPKsxKUY94XzrTSV3J0y1slb907DioU,9140
4
4
  ansible/context.py,sha256=oKYyfjfWpy8vDeProtqfnqSmuij_t75_5e5t0U_hQ1g,1933
5
5
  ansible/keyword_desc.yml,sha256=vE9joFgSeHR4Djl7Bd-HHVCrGByRCrTUmWYZ8LKPZKk,7412
6
- ansible/release.py,sha256=UGVEdqMoie0PB34BB5H53SbE26uuyBjT_ssn7gIbh_A,835
6
+ ansible/release.py,sha256=h1iqa3a1m652guMiR4N2-7RyXcnVwVbd6nbxEtKgbww,835
7
7
  ansible/_vendor/__init__.py,sha256=2QBeBwT7uG7M3Aw-pIdCpt6XPtHMCpbEKfACYKA7xIg,2033
8
8
  ansible/cli/__init__.py,sha256=fzgR82NIGBH3GujIMehhAaP4KYszn4uztuCaFYRUpGk,28718
9
9
  ansible/cli/adhoc.py,sha256=quJ9WzRzf3dz_dtDGmahNMffqyNVy1jzQCMo21YL5Qg,8194
@@ -26,7 +26,7 @@ ansible/compat/importlib_resources.py,sha256=oCjsu8foADOkMNwRuWiRCjQxO8zEOc-Olc2
26
26
  ansible/compat/selectors.py,sha256=pbI2QH2fT2WAOtmEBbd6Cp2yXyCBbb5TLR7iitqnAkU,1002
27
27
  ansible/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
28
  ansible/config/ansible_builtin_runtime.yml,sha256=nwL_-rqEEmpuSHxZH70pJBiEosDKOPkYIboH3_7LVEY,376076
29
- ansible/config/base.yml,sha256=GQIA4_S8F-4xFoiXsNAaTXlvoZes-SC-z6c0rxovl9g,85728
29
+ ansible/config/base.yml,sha256=4iotRTO8gAW_A19yBmYJAet1NIIulPbLA1b8TscyzbQ,85728
30
30
  ansible/config/manager.py,sha256=MvNZnqHDtz9uda5_ryNvpCv2M3frAl81bvZvgS1lGko,25730
31
31
  ansible/errors/__init__.py,sha256=pJ0Cd87ET5SNut851lrHH8EAoKEal2DdUJYl8yjRd8E,14739
32
32
  ansible/errors/yaml_strings.py,sha256=fKfgD3rC017dyMackTpu-LkvbsdnsfBAKCxMH-fDtIg,3858
@@ -37,7 +37,7 @@ ansible/executor/module_common.py,sha256=4pVfjMgCle9ttAZTeuwSx3Kdi0rljagyHC11i4V
37
37
  ansible/executor/play_iterator.py,sha256=FRzl8ELbICqzud-lT2KNuLmPoPntzayf2Y9DboEwso0,30427
38
38
  ansible/executor/playbook_executor.py,sha256=S_dwBYqYTQtN32AMQXxQTOpVCczV4KJ8ezergt1nlmA,15014
39
39
  ansible/executor/stats.py,sha256=gcBhJQrZTgE95737d6lArJ3FpTlbAfVt6GMhEqs5ZPU,3180
40
- ansible/executor/task_executor.py,sha256=dnt52xdlu9pK_0utDAMT8DBzXD6ixFY5vFPRGd3GMXU,60391
40
+ ansible/executor/task_executor.py,sha256=Q9Puu6y0wczvnLMrHaNSeg4FkhFqs6c3Kj6X_RvhII4,60551
41
41
  ansible/executor/task_queue_manager.py,sha256=wv19pq9LNHRABjvDYUZHQ9kmlO_ypA0r3aMaLnGxaCs,18640
42
42
  ansible/executor/task_result.py,sha256=pnLu-f0tYaDmDXSQftCBChSt_Zx5pW0GeLYLvEHuHkA,5695
43
43
  ansible/executor/discovery/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -140,9 +140,9 @@ ansible/inventory/host.py,sha256=PDb5OTplhfpUIvdHiP2BckUOB1gUl302N-3sW0_sTyg,503
140
140
  ansible/inventory/manager.py,sha256=45mHgZTAkQ3IjAtrgsNzJXvynC-HIEor-JJE-V3xXN4,29454
141
141
  ansible/module_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
142
142
  ansible/module_utils/_text.py,sha256=VkWgAnSNVCbTQqZgllUObBFsH3uM4EUW5srl1UR9t1g,544
143
- ansible/module_utils/ansible_release.py,sha256=UGVEdqMoie0PB34BB5H53SbE26uuyBjT_ssn7gIbh_A,835
143
+ ansible/module_utils/ansible_release.py,sha256=h1iqa3a1m652guMiR4N2-7RyXcnVwVbd6nbxEtKgbww,835
144
144
  ansible/module_utils/api.py,sha256=DWIuLW5gDWuyyDHLLgGnub42Qa8kagDdkf1xDeLAFl4,5784
145
- ansible/module_utils/basic.py,sha256=1BHf9_6SsFlfeTcYlOqOzbnITG3x8galaBcPm8ec6nE,85703
145
+ ansible/module_utils/basic.py,sha256=G5gg2b4L6y8u4J7pCRkoAAsIz8rabuAPB4ThFu2wvaY,85920
146
146
  ansible/module_utils/connection.py,sha256=q_BdUaST6E44ltHsWPOFOheXK9vKmzaJvP-eQOrOrmE,8394
147
147
  ansible/module_utils/errors.py,sha256=cOVAUZaQTeYaSGhKnYsT3L8vshayQHbCXzkT6HIVi_o,3345
148
148
  ansible/module_utils/json_utils.py,sha256=2WuR79zOoVVP4zo8iztwzE_k2JdXawpWh855YhdPIDU,3403
@@ -347,7 +347,7 @@ ansible/modules/wait_for_connection.py,sha256=lHgsuyw3oel1pqXlLCls7KSF1PJaSU0RKG
347
347
  ansible/modules/yum_repository.py,sha256=v9nsLd5NLy33ygJ_6IYzknFDPnZaGvyKemWEL5843qk,24906
348
348
  ansible/parsing/__init__.py,sha256=NMP9ZkK59SNdQktw76aWAXVAm5U2POXLgAK7wH-1h0g,742
349
349
  ansible/parsing/ajson.py,sha256=wr13wRYyK_VPBVki-5hisJZZKwi1T4rSi37gWj7zrOU,1254
350
- ansible/parsing/dataloader.py,sha256=Lm11qSwF3OD7kzrZJWit2UcrC8h1hExKXNPuAdli6eE,20953
350
+ ansible/parsing/dataloader.py,sha256=ocwvS5dQo5ocJGO1JO5hz1DI_CNSX_cKFr_pKunaNyM,20915
351
351
  ansible/parsing/mod_args.py,sha256=bDPfCFFYx9DwlJ16CHaIlWK8sXURqFSuJvXHtzcFxs0,14585
352
352
  ansible/parsing/plugin_docs.py,sha256=XBpeEALC-eBOZJPM4jPPxbKu0dYDRDyUG4STDUsrf9o,8661
353
353
  ansible/parsing/quoting.py,sha256=JokJozzFk7NDxDGTTZerfBntBls1NzNWyK7AQgsH5C8,1057
@@ -380,14 +380,14 @@ ansible/playbook/play_context.py,sha256=w5P-lAyN1cr01JgSLw8tnYy4QsSyDFLzbSy_ehuc
380
380
  ansible/playbook/playbook_include.py,sha256=hr3N_yV4unjhiC2IIdchY0TPSARwlv0SXH9bIsIrbaA,7493
381
381
  ansible/playbook/role_include.py,sha256=NCgDHtXlOltJ0XXSgGTTxDVrLC6IBe_d9SgNGXtsI20,7575
382
382
  ansible/playbook/taggable.py,sha256=PfbiQhDDafwKja2yIknJTEAHPspb7tPmCRDEO_8gmvY,3165
383
- ansible/playbook/task.py,sha256=K-qy32w9w_SK6tdPZRn5sobFOrYZFQt2eM9yC7SwKC4,21500
384
- ansible/playbook/task_include.py,sha256=eGJOfmJj9bgQoTwz3wFvD77x9qWK2rEi20qvA24XDzs,5234
383
+ ansible/playbook/task.py,sha256=VxFZY5gyAfhe40GTscpMy7f5Z6iLfTTCceGDUwpaKFU,21754
384
+ ansible/playbook/task_include.py,sha256=RHqzspHMA7wuIswDd6szZYCymXiVqWlF1Jil_2yRMz4,5244
385
385
  ansible/playbook/role/__init__.py,sha256=HSvzDNMq8DtNG4jQvZe1UAkR42vyj8Qt1ScgRBZ2MYE,29697
386
386
  ansible/playbook/role/definition.py,sha256=ZKs9FI3kqJETFHMh-8lOH6xGY_g2siuTxYgQj5VkcDk,9550
387
387
  ansible/playbook/role/include.py,sha256=9e4IvnD3JXqJUV-hB7riGgq0SjrqQGQHDg-cuJ1vTlo,2342
388
388
  ansible/playbook/role/metadata.py,sha256=HUuR5wCKAw-6urkAR4DKxUeOVsqFflSDHjZuWdBCmxo,5074
389
389
  ansible/playbook/role/requirement.py,sha256=CNgLa0J6zZk2YQ_aeALnjQvehkkFXhrK8LQQZs7Ztzc,4173
390
- ansible/plugins/__init__.py,sha256=aB1jIneBWDT_blrDUw-zimlKynpqXYkxgJ0hl7Mdnpo,5501
390
+ ansible/plugins/__init__.py,sha256=y4dYcAW6qvj2eaFQKxsJc2J5TXPPiXzXpVznk--Z0n0,5725
391
391
  ansible/plugins/list.py,sha256=c2wWNt1LMQj9URWS4JAJVlyzJqAj3CxUrauozN75crM,8919
392
392
  ansible/plugins/loader.py,sha256=BMUcCe2CltI95l3q56bEz_EjvaKLWB9XxthRCORFFJ0,75837
393
393
  ansible/plugins/action/__init__.py,sha256=H7bcYPA8io7m4d0zSYPZo65c2xRf44YoJNvkS2H1RnI,69202
@@ -437,8 +437,8 @@ ansible/plugins/cliconf/__init__.py,sha256=NlIs8a21RJSPOmoO-fVSJtO4OGNPxCAMFntDZ
437
437
  ansible/plugins/connection/__init__.py,sha256=7B9UmhcM4divUhg-RsurhOOGQiCVeLGGh0Zp_zCvK4w,17947
438
438
  ansible/plugins/connection/local.py,sha256=A-XQy_wIky16xrgkm2KW2jyZLpzmcUPjNOPtoQQnDJg,8339
439
439
  ansible/plugins/connection/paramiko_ssh.py,sha256=NnCHPiVZTzJVu0EQ4p4g0k0jxUgEHC9PHvuD6IFZ6O4,30045
440
- ansible/plugins/connection/psrp.py,sha256=1wihaS4h7-Yq2SVsQ9KI1ipxn7Jg9fvzmf7q7KannOw,36740
441
- ansible/plugins/connection/ssh.py,sha256=zTaDGv23CmIvrXqSkMmoosLnFecszJlaFl1fDD8BOMA,62811
440
+ ansible/plugins/connection/psrp.py,sha256=K3ZhDmpYcCI5CYtXBonD6hMb4QZe4GN6VZ6vKMPz4kk,36762
441
+ ansible/plugins/connection/ssh.py,sha256=zj_pSJk1SY3TVAXnYR6LMwmZvU5LWkTflXy_3SGG2Ag,62830
442
442
  ansible/plugins/connection/winrm.py,sha256=x9FHPRkEyI_ua4PUPbYVb7_joyMJYEiGSv45jxxkNTQ,40599
443
443
  ansible/plugins/doc_fragments/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
444
444
  ansible/plugins/doc_fragments/action_common_attributes.py,sha256=OaP2is2r9wm_f8gbLZhDDDwccg1joXMvJM72vbgcbIo,2442
@@ -547,7 +547,7 @@ ansible/plugins/inventory/toml.py,sha256=VqNEJjr0I4qhNAdliW3doof01_DcfVSUbYpX5yk
547
547
  ansible/plugins/inventory/yaml.py,sha256=bEvCjUdkDuMNE1N6o7_vTm-xmU6-SH2Jzmko4gUEq-0,7415
548
548
  ansible/plugins/lookup/__init__.py,sha256=lUifYWnyaWPK-PcLGH65Qa0nkyF2sogY3GI2LHl0yLY,4680
549
549
  ansible/plugins/lookup/config.py,sha256=ilQZ6AsZhk_Gc5MNGSPcj4dBf_EzEYf_9PwlgFHDz0c,6894
550
- ansible/plugins/lookup/csvfile.py,sha256=_mxDy5qVIVlpafzGFq0wOerRJOqYtWIvrR2E4Am06wo,6708
550
+ ansible/plugins/lookup/csvfile.py,sha256=3NDezWFG6syRg0HSaE_2iS1C_aMjgOv8l0htaGml7X0,7426
551
551
  ansible/plugins/lookup/dict.py,sha256=Df0P5QgcIE1LwqDPbM0L8CwtBqJPVrqTHy3AudFvQ84,2198
552
552
  ansible/plugins/lookup/env.py,sha256=MLMZNyzSuRLqBFYUjEhWa7exHJVnvqkgI4EmoYFS3iw,2646
553
553
  ansible/plugins/lookup/file.py,sha256=El1j6qgZb2hdlVNusMGO6eaYkHadfum7kHQuD06ZU98,3271
@@ -574,11 +574,11 @@ ansible/plugins/lookup/vars.py,sha256=eXVZdwumdcp3ajaDX7JyIYeGvQ6L-HxHGfnob9Pnkg
574
574
  ansible/plugins/netconf/__init__.py,sha256=50w1g2rhUo6L-xtiMT20jbR8WyOnhwNSRd2IRNSjNX4,17094
575
575
  ansible/plugins/shell/__init__.py,sha256=rEwatHZ46LJuxMFANb6e__CTLkFWX6B0878eBaCXwqM,9286
576
576
  ansible/plugins/shell/cmd.py,sha256=kPCSKrJJFH5XTkmteEI3P1Da6WfPSXxDnV39VFpgD-A,2170
577
- ansible/plugins/shell/powershell.py,sha256=4PcJG54USxhUDtWXhHUkVt8ixUtXEzg8J0qQwhlfSOA,11340
577
+ ansible/plugins/shell/powershell.py,sha256=6_loE4nYiLjro8egODcsK4HmoPmAk9bd4YY961dXb2U,12880
578
578
  ansible/plugins/shell/sh.py,sha256=wblaY2EGdA2O00gNuTVZVgVV08RH0e_g4V_AkE50Iws,3884
579
- ansible/plugins/strategy/__init__.py,sha256=pjT5mEI3a7N3SgIBXJcjQgpGC527rzddMuByN2tU4O4,57233
579
+ ansible/plugins/strategy/__init__.py,sha256=UdcdFDk8cPjPxa6ZlXyIJUi7B0Pf5dEPCjm73plgcTE,57037
580
580
  ansible/plugins/strategy/debug.py,sha256=yMmfT-lQHfR2y9bQcqrSPzqHuWZMo7V9y4ZWOXoboRE,1205
581
- ansible/plugins/strategy/free.py,sha256=b7ke-4s9IcHLJWmfP8gYzc_z5n2kI-v3D0YVQBtI4x8,16483
581
+ ansible/plugins/strategy/free.py,sha256=WNrpfg2B8fVcYC5qvBhn4uEH0Cc1-UmFzBH6Hhs3u_I,16728
582
582
  ansible/plugins/strategy/host_pinned.py,sha256=GrDDQCtohmmJn3t9VOPb0lUZK_nUWy0s__z5Tq_rHfI,1875
583
583
  ansible/plugins/strategy/linear.py,sha256=no9JgVrgqoN3SphXE38y3DTK1P9FpB48Qn21ro2qFZU,18394
584
584
  ansible/plugins/terminal/__init__.py,sha256=EqeJpMokRzuUMO66yYErPSyninjqNX0_5r55CEkTc4o,4420
@@ -666,7 +666,7 @@ ansible/utils/ssh_functions.py,sha256=DSxlfBO65EwnP18pmfNkJxx4sNRnPuj8tMP3X-Cjwp
666
666
  ansible/utils/unicode.py,sha256=__zbdElrMS9Rrqo9H7tF8zkjKFQCFU8kTtj5cVIITxM,1100
667
667
  ansible/utils/unsafe_proxy.py,sha256=RlAt3OHutmgYZD3dEqhqYjgPVLu7UzncnfhS6zJlwoM,12697
668
668
  ansible/utils/vars.py,sha256=qMmRZJiUbmSWtmHd30jW7oxKr0sAq7_BzvIYglJ_T7g,9843
669
- ansible/utils/version.py,sha256=t5i3orCsL9uCgr1yZ1ag_cPJzXti7CIvnGEHDE_TkY4,7705
669
+ ansible/utils/version.py,sha256=AKu8wtymk6pGYQpWaZ7vvVc-5m-OQoDAwZcs9B-L9-c,7736
670
670
  ansible/utils/collection_loader/__init__.py,sha256=ietIGihc75tjOuwbrk0keAi8RNLw2egfOCYrpQtckF4,1065
671
671
  ansible/utils/collection_loader/_collection_config.py,sha256=LsGtKWY68PUExSMOLXW4qVfi50o7Fv62j2KPudyC3vA,3094
672
672
  ansible/utils/collection_loader/_collection_finder.py,sha256=X4jKhMLld8RmpNgOVVv3nbuKsa6gAdDVyNwjHdk44MU,56584
@@ -678,7 +678,7 @@ ansible/vars/hostvars.py,sha256=ggUQ5luCajjX7sEvFCHpIuB_stWPRb089cZ3I1v1Vmo,5070
678
678
  ansible/vars/manager.py,sha256=ujVDQXWvy8BihIxGzBPX6fMeUl2AlclkwadKMo6VjSk,38583
679
679
  ansible/vars/plugins.py,sha256=RsRU9fiLcJwPIAyTYnmVZglsiEOMCIgQskflavE-XnE,4546
680
680
  ansible/vars/reserved.py,sha256=kZiQMPvaFin35006gLwDpX16w-9xlu6EaL4LSTKP40U,2531
681
- ansible_core-2.17.3rc1.data/scripts/ansible-test,sha256=dyY2HtRZotRQO3b89HGXY_KnJgBvgsm4eLIe4B2LUoA,1637
681
+ ansible_core-2.17.4rc1.data/scripts/ansible-test,sha256=dyY2HtRZotRQO3b89HGXY_KnJgBvgsm4eLIe4B2LUoA,1637
682
682
  ansible_test/__init__.py,sha256=20VPOj11c6Ut1Av9RaurgwJvFhMqkWG3vAvcCbecNKw,66
683
683
  ansible_test/_data/ansible.cfg,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
684
684
  ansible_test/_data/coveragerc,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -906,7 +906,7 @@ ansible_test/_util/controller/sanity/code-smell/no-smart-quotes.py,sha256=4LFlim
906
906
  ansible_test/_util/controller/sanity/code-smell/replace-urlopen.json,sha256=w9--s9c-2F26o7JBJbTJjVGPnvlwGNfSu7KNDSmL9Qw,179
907
907
  ansible_test/_util/controller/sanity/code-smell/replace-urlopen.py,sha256=PSLEuYW5SBrcC7YIt8jdvJ3arxLL7SK7Mxbsvz1UfXc,624
908
908
  ansible_test/_util/controller/sanity/code-smell/runtime-metadata.json,sha256=H2E2-01YXLlSWjvLJT5Vtj3Gn4zB6xhPXsDJh4a7EH0,225
909
- ansible_test/_util/controller/sanity/code-smell/runtime-metadata.py,sha256=Hjf8KqEgEa-K2pZ8E0hKQ80BMTX1slCz0Hp2P1CZWn8,12183
909
+ ansible_test/_util/controller/sanity/code-smell/runtime-metadata.py,sha256=ozoaAQCTZM-0Hnl--jSUwbZS0mBrs6FGWbP6_esODzk,12233
910
910
  ansible_test/_util/controller/sanity/code-smell/shebang.json,sha256=3vtNzoowM53gi2KZi9peIKVIU79ulQY3FE0jYcSP77M,63
911
911
  ansible_test/_util/controller/sanity/code-smell/shebang.py,sha256=AKCti3RCgZy0GWB3bXgimr_OhqfVPOp_I7345UN_DV8,4672
912
912
  ansible_test/_util/controller/sanity/code-smell/symlinks.json,sha256=JkalgX52aKGUKqjKG5P-68F0tXmUMgldPrNAknMN2Fk,96
@@ -979,9 +979,9 @@ ansible_test/config/cloud-config-vultr.ini.template,sha256=XLKHk3lg_8ReQMdWfZzhh
979
979
  ansible_test/config/config.yml,sha256=wb3knoBmZewG3GWOMnRHoVPQWW4vPixKLPMNS6vJmTc,2620
980
980
  ansible_test/config/inventory.networking.template,sha256=bFNSk8zNQOaZ_twaflrY0XZ9mLwUbRLuNT0BdIFwvn4,1335
981
981
  ansible_test/config/inventory.winrm.template,sha256=1QU8W-GFLnYEw8yY9bVIvUAVvJYPM3hyoijf6-M7T00,1098
982
- ansible_core-2.17.3rc1.dist-info/COPYING,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
983
- ansible_core-2.17.3rc1.dist-info/METADATA,sha256=r4JiqS44_wwZN5yKavnaP3x1sJ6j6g9ab9IRKX0V5Wg,6948
984
- ansible_core-2.17.3rc1.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
985
- ansible_core-2.17.3rc1.dist-info/entry_points.txt,sha256=0mpmsrIhODChxKl3eS-NcVQCaMetBn8KdPLtVxQgR64,453
986
- ansible_core-2.17.3rc1.dist-info/top_level.txt,sha256=IFbRLjAvih1DYzJWg3_F6t4sCzEMxRO7TOMNs6GkYHo,21
987
- ansible_core-2.17.3rc1.dist-info/RECORD,,
982
+ ansible_core-2.17.4rc1.dist-info/COPYING,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
983
+ ansible_core-2.17.4rc1.dist-info/METADATA,sha256=ZGJlKw5k4Qja8N5t4yuvA0dZixCy2n99lGETpuWsHpc,6948
984
+ ansible_core-2.17.4rc1.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
985
+ ansible_core-2.17.4rc1.dist-info/entry_points.txt,sha256=0mpmsrIhODChxKl3eS-NcVQCaMetBn8KdPLtVxQgR64,453
986
+ ansible_core-2.17.4rc1.dist-info/top_level.txt,sha256=IFbRLjAvih1DYzJWg3_F6t4sCzEMxRO7TOMNs6GkYHo,21
987
+ ansible_core-2.17.4rc1.dist-info/RECORD,,
@@ -123,7 +123,9 @@ def get_collection_version():
123
123
  # noinspection PyBroadException
124
124
  try:
125
125
  result = collection_detail.read_manifest_json('.') or collection_detail.read_galaxy_yml('.')
126
- return SemanticVersion(result['version'])
126
+ version = SemanticVersion()
127
+ version.parse(result['version'])
128
+ return version
127
129
  except Exception: # pylint: disable=broad-except
128
130
  # We do not care why it fails, in case we cannot get the version
129
131
  # just return None to indicate "we don't know".