ansible-core 2.20.0b1__py3-none-any.whl → 2.20.0rc1__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/cli/doc.py +3 -1
- ansible/collections/list.py +4 -2
- ansible/executor/process/worker.py +17 -11
- ansible/executor/task_queue_manager.py +43 -1
- ansible/galaxy/collection/__init__.py +7 -4
- ansible/galaxy/dependency_resolution/__init__.py +10 -9
- ansible/galaxy/dependency_resolution/dataclasses.py +86 -60
- ansible/galaxy/dependency_resolution/providers.py +53 -132
- ansible/galaxy/dependency_resolution/versioning.py +2 -4
- ansible/module_utils/ansible_release.py +1 -1
- ansible/module_utils/six/__init__.py +8 -0
- ansible/modules/known_hosts.py +7 -1
- ansible/parsing/dataloader.py +2 -2
- ansible/playbook/block.py +1 -3
- ansible/playbook/helpers.py +15 -13
- ansible/playbook/play.py +2 -12
- ansible/plugins/action/fetch.py +1 -1
- ansible/plugins/test/falsy.yml +1 -1
- ansible/plugins/test/truthy.yml +1 -1
- ansible/release.py +1 -1
- ansible/vars/manager.py +1 -2
- {ansible_core-2.20.0b1.dist-info → ansible_core-2.20.0rc1.dist-info}/METADATA +2 -2
- {ansible_core-2.20.0b1.dist-info → ansible_core-2.20.0rc1.dist-info}/RECORD +50 -50
- ansible_test/_data/completion/docker.txt +7 -7
- ansible_test/_data/requirements/ansible-test.txt +1 -1
- ansible_test/_data/requirements/ansible.txt +1 -1
- ansible_test/_data/requirements/sanity.ansible-doc.txt +2 -2
- ansible_test/_data/requirements/sanity.changelog.txt +1 -1
- ansible_test/_data/requirements/sanity.import.plugin.txt +2 -2
- ansible_test/_data/requirements/sanity.import.txt +1 -1
- ansible_test/_data/requirements/sanity.integration-aliases.txt +1 -1
- ansible_test/_data/requirements/sanity.pylint.txt +5 -5
- ansible_test/_data/requirements/sanity.runtime-metadata.txt +1 -1
- ansible_test/_data/requirements/sanity.validate-modules.txt +2 -2
- ansible_test/_data/requirements/sanity.yamllint.txt +1 -1
- ansible_test/_internal/commands/sanity/pylint.py +11 -0
- ansible_test/_internal/coverage_util.py +1 -1
- ansible_test/_internal/python_requirements.py +1 -1
- ansible_test/_util/controller/sanity/pylint/plugins/deprecated_calls.py +48 -45
- ansible_test/_util/controller/sanity/pylint/plugins/string_format.py +9 -7
- ansible_test/_util/controller/sanity/pylint/plugins/unwanted.py +25 -14
- {ansible_core-2.20.0b1.dist-info → ansible_core-2.20.0rc1.dist-info}/WHEEL +0 -0
- {ansible_core-2.20.0b1.dist-info → ansible_core-2.20.0rc1.dist-info}/entry_points.txt +0 -0
- {ansible_core-2.20.0b1.dist-info → ansible_core-2.20.0rc1.dist-info}/licenses/COPYING +0 -0
- {ansible_core-2.20.0b1.dist-info → ansible_core-2.20.0rc1.dist-info}/licenses/licenses/Apache-License.txt +0 -0
- {ansible_core-2.20.0b1.dist-info → ansible_core-2.20.0rc1.dist-info}/licenses/licenses/BSD-3-Clause.txt +0 -0
- {ansible_core-2.20.0b1.dist-info → ansible_core-2.20.0rc1.dist-info}/licenses/licenses/MIT-license.txt +0 -0
- {ansible_core-2.20.0b1.dist-info → ansible_core-2.20.0rc1.dist-info}/licenses/licenses/PSF-license.txt +0 -0
- {ansible_core-2.20.0b1.dist-info → ansible_core-2.20.0rc1.dist-info}/licenses/licenses/simplified_bsd.txt +0 -0
- {ansible_core-2.20.0b1.dist-info → ansible_core-2.20.0rc1.dist-info}/top_level.txt +0 -0
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
from __future__ import annotations
|
|
7
7
|
|
|
8
|
+
import collections.abc as _c
|
|
8
9
|
import functools
|
|
9
10
|
import typing as t
|
|
10
11
|
|
|
@@ -15,6 +16,8 @@ if t.TYPE_CHECKING:
|
|
|
15
16
|
from ansible.galaxy.collection.galaxy_api_proxy import MultiGalaxyAPIProxy
|
|
16
17
|
from ansible.galaxy.api import GalaxyAPI
|
|
17
18
|
|
|
19
|
+
from resolvelib.structs import RequirementInformation
|
|
20
|
+
|
|
18
21
|
from ansible.galaxy.collection.gpg import get_signature_from_source
|
|
19
22
|
from ansible.galaxy.dependency_resolution.dataclasses import (
|
|
20
23
|
Candidate,
|
|
@@ -37,24 +40,24 @@ except ImportError:
|
|
|
37
40
|
|
|
38
41
|
|
|
39
42
|
# TODO: add python requirements to ansible-test's ansible-core distribution info and remove the hardcoded lowerbound/upperbound fallback
|
|
40
|
-
RESOLVELIB_LOWERBOUND = SemanticVersion("0.
|
|
43
|
+
RESOLVELIB_LOWERBOUND = SemanticVersion("0.8.0")
|
|
41
44
|
RESOLVELIB_UPPERBOUND = SemanticVersion("2.0.0")
|
|
42
45
|
RESOLVELIB_VERSION = SemanticVersion.from_loose_version(LooseVersion(resolvelib_version))
|
|
43
46
|
|
|
44
47
|
|
|
45
|
-
class
|
|
48
|
+
class CollectionDependencyProvider(AbstractProvider):
|
|
46
49
|
"""Delegate providing a requirement interface for the resolver."""
|
|
47
50
|
|
|
48
51
|
def __init__(
|
|
49
|
-
self,
|
|
50
|
-
apis
|
|
51
|
-
concrete_artifacts_manager
|
|
52
|
-
preferred_candidates
|
|
53
|
-
with_deps=True,
|
|
54
|
-
with_pre_releases=False,
|
|
55
|
-
upgrade=False,
|
|
56
|
-
include_signatures=True,
|
|
57
|
-
)
|
|
52
|
+
self,
|
|
53
|
+
apis: MultiGalaxyAPIProxy,
|
|
54
|
+
concrete_artifacts_manager: ConcreteArtifactsManager,
|
|
55
|
+
preferred_candidates: _c.Iterable[Candidate] | None = None,
|
|
56
|
+
with_deps: bool = True,
|
|
57
|
+
with_pre_releases: bool = False,
|
|
58
|
+
upgrade: bool = False,
|
|
59
|
+
include_signatures: bool = True,
|
|
60
|
+
) -> None:
|
|
58
61
|
r"""Initialize helper attributes.
|
|
59
62
|
|
|
60
63
|
:param api: An instance of the multiple Galaxy APIs wrapper.
|
|
@@ -90,8 +93,10 @@ class CollectionDependencyProviderBase(AbstractProvider):
|
|
|
90
93
|
self._upgrade = upgrade
|
|
91
94
|
self._include_signatures = include_signatures
|
|
92
95
|
|
|
93
|
-
def identify(
|
|
94
|
-
|
|
96
|
+
def identify(
|
|
97
|
+
self,
|
|
98
|
+
requirement_or_candidate: Candidate | Requirement,
|
|
99
|
+
) -> str:
|
|
95
100
|
"""Given requirement or candidate, return an identifier for it.
|
|
96
101
|
|
|
97
102
|
This is used to identify a requirement or candidate, e.g.
|
|
@@ -102,8 +107,19 @@ class CollectionDependencyProviderBase(AbstractProvider):
|
|
|
102
107
|
"""
|
|
103
108
|
return requirement_or_candidate.canonical_package_id
|
|
104
109
|
|
|
105
|
-
def get_preference(
|
|
106
|
-
|
|
110
|
+
def get_preference(
|
|
111
|
+
self,
|
|
112
|
+
identifier: str,
|
|
113
|
+
resolutions: _c.Mapping[str, Candidate],
|
|
114
|
+
candidates: _c.Mapping[str, _c.Iterator[Candidate]],
|
|
115
|
+
information: _c.Mapping[
|
|
116
|
+
str,
|
|
117
|
+
_c.Iterator[RequirementInformation[Requirement, Candidate]],
|
|
118
|
+
],
|
|
119
|
+
backtrack_causes: _c.Sequence[
|
|
120
|
+
RequirementInformation[Requirement, Candidate],
|
|
121
|
+
],
|
|
122
|
+
) -> float | int:
|
|
107
123
|
"""Return sort key function return value for given requirement.
|
|
108
124
|
|
|
109
125
|
This result should be based on preference that is defined as
|
|
@@ -111,38 +127,6 @@ class CollectionDependencyProviderBase(AbstractProvider):
|
|
|
111
127
|
The lower the return value is, the more preferred this
|
|
112
128
|
group of arguments is.
|
|
113
129
|
|
|
114
|
-
resolvelib >=0.5.3, <0.7.0
|
|
115
|
-
|
|
116
|
-
:param resolution: Currently pinned candidate, or ``None``.
|
|
117
|
-
|
|
118
|
-
:param candidates: A list of possible candidates.
|
|
119
|
-
|
|
120
|
-
:param information: A list of requirement information.
|
|
121
|
-
|
|
122
|
-
Each ``information`` instance is a named tuple with two entries:
|
|
123
|
-
|
|
124
|
-
* ``requirement`` specifies a requirement contributing to
|
|
125
|
-
the current candidate list
|
|
126
|
-
|
|
127
|
-
* ``parent`` specifies the candidate that provides
|
|
128
|
-
(depended on) the requirement, or `None`
|
|
129
|
-
to indicate a root requirement.
|
|
130
|
-
|
|
131
|
-
resolvelib >=0.7.0, < 0.8.0
|
|
132
|
-
|
|
133
|
-
:param identifier: The value returned by ``identify()``.
|
|
134
|
-
|
|
135
|
-
:param resolutions: Mapping of identifier, candidate pairs.
|
|
136
|
-
|
|
137
|
-
:param candidates: Possible candidates for the identifier.
|
|
138
|
-
Mapping of identifier, list of candidate pairs.
|
|
139
|
-
|
|
140
|
-
:param information: Requirement information of each package.
|
|
141
|
-
Mapping of identifier, list of named tuple pairs.
|
|
142
|
-
The named tuples have the entries ``requirement`` and ``parent``.
|
|
143
|
-
|
|
144
|
-
resolvelib >=0.8.0, <= 1.0.1
|
|
145
|
-
|
|
146
130
|
:param identifier: The value returned by ``identify()``.
|
|
147
131
|
|
|
148
132
|
:param resolutions: Mapping of identifier, candidate pairs.
|
|
@@ -178,10 +162,6 @@ class CollectionDependencyProviderBase(AbstractProvider):
|
|
|
178
162
|
the value is, the more preferred this requirement is (i.e. the
|
|
179
163
|
sorting function is called with ``reverse=False``).
|
|
180
164
|
"""
|
|
181
|
-
raise NotImplementedError
|
|
182
|
-
|
|
183
|
-
def _get_preference(self, candidates):
|
|
184
|
-
# type: (list[Candidate]) -> t.Union[float, int]
|
|
185
165
|
if any(
|
|
186
166
|
candidate in self._preferred_candidates
|
|
187
167
|
for candidate in candidates
|
|
@@ -191,8 +171,12 @@ class CollectionDependencyProviderBase(AbstractProvider):
|
|
|
191
171
|
return float('-inf')
|
|
192
172
|
return len(candidates)
|
|
193
173
|
|
|
194
|
-
def find_matches(
|
|
195
|
-
|
|
174
|
+
def find_matches(
|
|
175
|
+
self,
|
|
176
|
+
identifier: str,
|
|
177
|
+
requirements: _c.Mapping[str, _c.Iterator[Requirement]],
|
|
178
|
+
incompatibilities: _c.Mapping[str, _c.Iterator[Candidate]],
|
|
179
|
+
) -> list[Candidate]:
|
|
196
180
|
r"""Find all possible candidates satisfying given requirements.
|
|
197
181
|
|
|
198
182
|
This tries to get candidates based on the requirements' types.
|
|
@@ -203,32 +187,13 @@ class CollectionDependencyProviderBase(AbstractProvider):
|
|
|
203
187
|
For a "named" requirement, Galaxy-compatible APIs are consulted
|
|
204
188
|
to find concrete candidates for this requirement. If there's a
|
|
205
189
|
pre-installed candidate, it's prepended in front of others.
|
|
206
|
-
|
|
207
|
-
resolvelib >=0.5.3, <0.6.0
|
|
208
|
-
|
|
209
|
-
:param requirements: A collection of requirements which all of \
|
|
210
|
-
the returned candidates must match. \
|
|
211
|
-
All requirements are guaranteed to have \
|
|
212
|
-
the same identifier. \
|
|
213
|
-
The collection is never empty.
|
|
214
|
-
|
|
215
|
-
resolvelib >=0.6.0
|
|
216
|
-
|
|
217
|
-
:param identifier: The value returned by ``identify()``.
|
|
218
|
-
|
|
219
|
-
:param requirements: The requirements all returned candidates must satisfy.
|
|
220
|
-
Mapping of identifier, iterator of requirement pairs.
|
|
221
|
-
|
|
222
|
-
:param incompatibilities: Incompatible versions that must be excluded
|
|
223
|
-
from the returned list.
|
|
224
|
-
|
|
225
|
-
:returns: An iterable that orders candidates by preference, \
|
|
226
|
-
e.g. the most preferred candidate comes first.
|
|
227
190
|
"""
|
|
228
|
-
|
|
191
|
+
return [
|
|
192
|
+
match for match in self._find_matches(list(requirements[identifier]))
|
|
193
|
+
if not any(match.ver == incompat.ver for incompat in incompatibilities[identifier])
|
|
194
|
+
]
|
|
229
195
|
|
|
230
|
-
def _find_matches(self, requirements):
|
|
231
|
-
# type: (list[Requirement]) -> list[Candidate]
|
|
196
|
+
def _find_matches(self, requirements: list[Requirement]) -> list[Candidate]:
|
|
232
197
|
# FIXME: The first requirement may be a Git repo followed by
|
|
233
198
|
# FIXME: its cloned tmp dir. Using only the first one creates
|
|
234
199
|
# FIXME: loops that prevent any further dependency exploration.
|
|
@@ -249,7 +214,10 @@ class CollectionDependencyProviderBase(AbstractProvider):
|
|
|
249
214
|
all(self.is_satisfied_by(requirement, candidate) for requirement in requirements)
|
|
250
215
|
}
|
|
251
216
|
try:
|
|
252
|
-
coll_versions
|
|
217
|
+
coll_versions: _c.Iterable[tuple[str, GalaxyAPI]] = (
|
|
218
|
+
[] if preinstalled_candidates
|
|
219
|
+
else self._api_proxy.get_collection_versions(first_req)
|
|
220
|
+
)
|
|
253
221
|
except TypeError as exc:
|
|
254
222
|
if first_req.is_concrete_artifact:
|
|
255
223
|
# Non hashable versions will cause a TypeError
|
|
@@ -292,7 +260,7 @@ class CollectionDependencyProviderBase(AbstractProvider):
|
|
|
292
260
|
|
|
293
261
|
latest_matches = []
|
|
294
262
|
signatures = []
|
|
295
|
-
extra_signature_sources
|
|
263
|
+
extra_signature_sources: list[str] = []
|
|
296
264
|
|
|
297
265
|
discarding_pre_releases_acceptable = any(
|
|
298
266
|
not is_pre_release(candidate_version)
|
|
@@ -397,8 +365,11 @@ class CollectionDependencyProviderBase(AbstractProvider):
|
|
|
397
365
|
|
|
398
366
|
return list(preinstalled_candidates) + latest_matches
|
|
399
367
|
|
|
400
|
-
def is_satisfied_by(
|
|
401
|
-
|
|
368
|
+
def is_satisfied_by(
|
|
369
|
+
self,
|
|
370
|
+
requirement: Requirement,
|
|
371
|
+
candidate: Candidate,
|
|
372
|
+
) -> bool:
|
|
402
373
|
r"""Whether the given requirement is satisfiable by a candidate.
|
|
403
374
|
|
|
404
375
|
:param requirement: A requirement that produced the `candidate`.
|
|
@@ -424,8 +395,7 @@ class CollectionDependencyProviderBase(AbstractProvider):
|
|
|
424
395
|
requirements=requirement.ver,
|
|
425
396
|
)
|
|
426
397
|
|
|
427
|
-
def get_dependencies(self, candidate):
|
|
428
|
-
# type: (Candidate) -> list[Candidate]
|
|
398
|
+
def get_dependencies(self, candidate: Candidate) -> list[Requirement]:
|
|
429
399
|
r"""Get direct dependencies of a candidate.
|
|
430
400
|
|
|
431
401
|
:returns: A collection of requirements that `candidate` \
|
|
@@ -456,52 +426,3 @@ class CollectionDependencyProviderBase(AbstractProvider):
|
|
|
456
426
|
self._make_req_from_dict({'name': dep_name, 'version': dep_req})
|
|
457
427
|
for dep_name, dep_req in req_map.items()
|
|
458
428
|
]
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
# Classes to handle resolvelib API changes between minor versions for 0.X
|
|
462
|
-
class CollectionDependencyProvider050(CollectionDependencyProviderBase):
|
|
463
|
-
def find_matches(self, requirements): # type: ignore[override]
|
|
464
|
-
# type: (list[Requirement]) -> list[Candidate]
|
|
465
|
-
return self._find_matches(requirements)
|
|
466
|
-
|
|
467
|
-
def get_preference(self, resolution, candidates, information): # type: ignore[override]
|
|
468
|
-
# type: (t.Optional[Candidate], list[Candidate], list[t.NamedTuple]) -> t.Union[float, int]
|
|
469
|
-
return self._get_preference(candidates)
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
class CollectionDependencyProvider060(CollectionDependencyProviderBase):
|
|
473
|
-
def find_matches(self, identifier, requirements, incompatibilities): # type: ignore[override]
|
|
474
|
-
# type: (str, t.Mapping[str, t.Iterator[Requirement]], t.Mapping[str, t.Iterator[Requirement]]) -> list[Candidate]
|
|
475
|
-
return [
|
|
476
|
-
match for match in self._find_matches(list(requirements[identifier]))
|
|
477
|
-
if not any(match.ver == incompat.ver for incompat in incompatibilities[identifier])
|
|
478
|
-
]
|
|
479
|
-
|
|
480
|
-
def get_preference(self, resolution, candidates, information): # type: ignore[override]
|
|
481
|
-
# type: (t.Optional[Candidate], list[Candidate], list[t.NamedTuple]) -> t.Union[float, int]
|
|
482
|
-
return self._get_preference(candidates)
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
class CollectionDependencyProvider070(CollectionDependencyProvider060):
|
|
486
|
-
def get_preference(self, identifier, resolutions, candidates, information): # type: ignore[override]
|
|
487
|
-
# type: (str, t.Mapping[str, Candidate], t.Mapping[str, t.Iterator[Candidate]], t.Iterator[t.NamedTuple]) -> t.Union[float, int]
|
|
488
|
-
return self._get_preference(list(candidates[identifier]))
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
class CollectionDependencyProvider080(CollectionDependencyProvider060):
|
|
492
|
-
def get_preference(self, identifier, resolutions, candidates, information, backtrack_causes): # type: ignore[override]
|
|
493
|
-
# type: (str, t.Mapping[str, Candidate], t.Mapping[str, t.Iterator[Candidate]], t.Iterator[t.NamedTuple], t.Sequence) -> t.Union[float, int]
|
|
494
|
-
return self._get_preference(list(candidates[identifier]))
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
def _get_provider(): # type () -> CollectionDependencyProviderBase
|
|
498
|
-
if RESOLVELIB_VERSION >= SemanticVersion("0.8.0"):
|
|
499
|
-
return CollectionDependencyProvider080
|
|
500
|
-
if RESOLVELIB_VERSION >= SemanticVersion("0.7.0"):
|
|
501
|
-
return CollectionDependencyProvider070
|
|
502
|
-
if RESOLVELIB_VERSION >= SemanticVersion("0.6.0"):
|
|
503
|
-
return CollectionDependencyProvider060
|
|
504
|
-
return CollectionDependencyProvider050
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
CollectionDependencyProvider = _get_provider()
|
|
@@ -11,8 +11,7 @@ from ansible.module_utils.compat.version import LooseVersion
|
|
|
11
11
|
from ansible.utils.version import SemanticVersion
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
def is_pre_release(version):
|
|
15
|
-
# type: (str) -> bool
|
|
14
|
+
def is_pre_release(version: str) -> bool:
|
|
16
15
|
"""Figure out if a given version is a pre-release."""
|
|
17
16
|
try:
|
|
18
17
|
return SemanticVersion(version).is_prerelease
|
|
@@ -20,8 +19,7 @@ def is_pre_release(version):
|
|
|
20
19
|
return False
|
|
21
20
|
|
|
22
21
|
|
|
23
|
-
def meets_requirements(version, requirements):
|
|
24
|
-
# type: (str, str) -> bool
|
|
22
|
+
def meets_requirements(version: str, requirements: str) -> bool:
|
|
25
23
|
"""Verify if a given version satisfies all the requirements.
|
|
26
24
|
|
|
27
25
|
Supported version identifiers are:
|
|
@@ -33,6 +33,14 @@ import operator
|
|
|
33
33
|
import sys
|
|
34
34
|
import types
|
|
35
35
|
|
|
36
|
+
from ansible.module_utils.common import warnings as _warnings
|
|
37
|
+
|
|
38
|
+
_warnings.deprecate(
|
|
39
|
+
msg="The `ansible.module_utils.six` module is deprecated.",
|
|
40
|
+
help_text="Use the Python standard library equivalent instead.",
|
|
41
|
+
version="2.24",
|
|
42
|
+
)
|
|
43
|
+
|
|
36
44
|
# The following makes it easier for us to script updates of the bundled code. It is not part of
|
|
37
45
|
# upstream six
|
|
38
46
|
_BUNDLED_METADATA = {"pypi_name": "six", "version": "1.17.0"}
|
ansible/modules/known_hosts.py
CHANGED
|
@@ -225,7 +225,13 @@ def sanity_check(module, host, key, sshkeygen):
|
|
|
225
225
|
rc, stdout, stderr = module.run_command(sshkeygen_command)
|
|
226
226
|
|
|
227
227
|
if stdout == '': # host not found
|
|
228
|
-
|
|
228
|
+
results = {
|
|
229
|
+
"msg": "Host parameter does not match hashed host field in supplied key",
|
|
230
|
+
"rc": rc,
|
|
231
|
+
}
|
|
232
|
+
if stderr:
|
|
233
|
+
results["stderr"] = stderr
|
|
234
|
+
module.fail_json(**results)
|
|
229
235
|
|
|
230
236
|
|
|
231
237
|
def search_for_host_key(module, host, key, path, sshkeygen):
|
ansible/parsing/dataloader.py
CHANGED
|
@@ -54,7 +54,7 @@ class DataLoader:
|
|
|
54
54
|
|
|
55
55
|
def __init__(self) -> None:
|
|
56
56
|
|
|
57
|
-
self._basedir: str = '.'
|
|
57
|
+
self._basedir: str = os.path.abspath('.')
|
|
58
58
|
|
|
59
59
|
# NOTE: not effective with forks as the main copy does not get updated.
|
|
60
60
|
# avoids rereading files
|
|
@@ -227,7 +227,7 @@ class DataLoader:
|
|
|
227
227
|
|
|
228
228
|
def set_basedir(self, basedir: str) -> None:
|
|
229
229
|
""" sets the base directory, used to find files when a relative path is given """
|
|
230
|
-
self._basedir = basedir
|
|
230
|
+
self._basedir = os.path.abspath(basedir)
|
|
231
231
|
|
|
232
232
|
def path_dwim(self, given: str) -> str:
|
|
233
233
|
"""
|
ansible/playbook/block.py
CHANGED
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
|
|
18
18
|
from __future__ import annotations
|
|
19
19
|
|
|
20
|
-
import ansible.constants as C
|
|
21
20
|
from ansible.errors import AnsibleParserError
|
|
22
21
|
from ansible.module_utils.common.sentinel import Sentinel
|
|
23
22
|
from ansible.playbook.attribute import NonInheritableFieldAttribute
|
|
@@ -316,8 +315,7 @@ class Block(Base, Conditional, CollectionSearch, Taggable, Notifiable, Delegatab
|
|
|
316
315
|
filtered_block = evaluate_block(task)
|
|
317
316
|
if filtered_block.has_tasks():
|
|
318
317
|
tmp_list.append(filtered_block)
|
|
319
|
-
elif
|
|
320
|
-
task.evaluate_tags(self._play.only_tags, self._play.skip_tags, all_vars=all_vars)):
|
|
318
|
+
elif task.evaluate_tags(self._play.only_tags, self._play.skip_tags, all_vars=all_vars):
|
|
321
319
|
tmp_list.append(task)
|
|
322
320
|
return tmp_list
|
|
323
321
|
|
ansible/playbook/helpers.py
CHANGED
|
@@ -165,17 +165,29 @@ def load_list_of_tasks(ds, play, block=None, role=None, task_include=None, use_h
|
|
|
165
165
|
subdir = 'tasks'
|
|
166
166
|
if use_handlers:
|
|
167
167
|
subdir = 'handlers'
|
|
168
|
+
try:
|
|
169
|
+
include_target = templar.template(task.args['_raw_params'])
|
|
170
|
+
except AnsibleUndefinedVariable as ex:
|
|
171
|
+
raise AnsibleParserError(
|
|
172
|
+
message=f"Error when evaluating variable in import path {task.args['_raw_params']!r}.",
|
|
173
|
+
help_text="When using static imports, ensure that any variables used in their names are defined in vars/vars_files\n"
|
|
174
|
+
"or extra-vars passed in from the command line. Static imports cannot use variables from facts or inventory\n"
|
|
175
|
+
"sources like group or host vars.",
|
|
176
|
+
obj=task_ds,
|
|
177
|
+
) from ex
|
|
178
|
+
# FIXME this appears to be (almost?) duplicate code as in IncludedFile for include_tasks
|
|
168
179
|
while parent_include is not None:
|
|
169
180
|
if not isinstance(parent_include, TaskInclude):
|
|
170
181
|
parent_include = parent_include._parent
|
|
171
182
|
continue
|
|
172
|
-
parent_include
|
|
173
|
-
|
|
183
|
+
if isinstance(parent_include, IncludeRole):
|
|
184
|
+
parent_include_dir = parent_include._role_path
|
|
185
|
+
else:
|
|
186
|
+
parent_include_dir = os.path.dirname(templar.template(parent_include.args.get('_raw_params')))
|
|
174
187
|
if cumulative_path is None:
|
|
175
188
|
cumulative_path = parent_include_dir
|
|
176
189
|
elif not os.path.isabs(cumulative_path):
|
|
177
190
|
cumulative_path = os.path.join(parent_include_dir, cumulative_path)
|
|
178
|
-
include_target = templar.template(task.args['_raw_params'])
|
|
179
191
|
if task._role:
|
|
180
192
|
new_basedir = os.path.join(task._role._role_path, subdir, cumulative_path)
|
|
181
193
|
include_file = loader.path_dwim_relative(new_basedir, subdir, include_target)
|
|
@@ -189,16 +201,6 @@ def load_list_of_tasks(ds, play, block=None, role=None, task_include=None, use_h
|
|
|
189
201
|
parent_include = parent_include._parent
|
|
190
202
|
|
|
191
203
|
if not found:
|
|
192
|
-
try:
|
|
193
|
-
include_target = templar.template(task.args['_raw_params'])
|
|
194
|
-
except AnsibleUndefinedVariable as ex:
|
|
195
|
-
raise AnsibleParserError(
|
|
196
|
-
message=f"Error when evaluating variable in import path {task.args['_raw_params']!r}.",
|
|
197
|
-
help_text="When using static imports, ensure that any variables used in their names are defined in vars/vars_files\n"
|
|
198
|
-
"or extra-vars passed in from the command line. Static imports cannot use variables from facts or inventory\n"
|
|
199
|
-
"sources like group or host vars.",
|
|
200
|
-
obj=task_ds,
|
|
201
|
-
) from ex
|
|
202
204
|
if task._role:
|
|
203
205
|
include_file = loader.path_dwim_relative(task._role._role_path, subdir, include_target)
|
|
204
206
|
else:
|
ansible/playbook/play.py
CHANGED
|
@@ -314,19 +314,9 @@ class Play(Base, Taggable, CollectionSearch):
|
|
|
314
314
|
t.args['_raw_params'] = 'flush_handlers'
|
|
315
315
|
t.implicit = True
|
|
316
316
|
t.set_loader(self._loader)
|
|
317
|
+
t.tags = ['always']
|
|
317
318
|
|
|
318
|
-
|
|
319
|
-
# Avoid calling flush_handlers in case the whole play is skipped on tags,
|
|
320
|
-
# this could be performance improvement since calling flush_handlers on
|
|
321
|
-
# large inventories could be expensive even if no hosts are notified
|
|
322
|
-
# since we call flush_handlers per host.
|
|
323
|
-
# Block.filter_tagged_tasks ignores evaluating tags on implicit meta
|
|
324
|
-
# tasks so we need to explicitly call Task.evaluate_tags here.
|
|
325
|
-
t.tags = self.tags
|
|
326
|
-
if t.evaluate_tags(self.only_tags, self.skip_tags, all_vars=self.vars):
|
|
327
|
-
flush_block.block = [t]
|
|
328
|
-
else:
|
|
329
|
-
flush_block.block = [t]
|
|
319
|
+
flush_block.block = [t]
|
|
330
320
|
|
|
331
321
|
# NOTE keep flush_handlers tasks even if a section has no regular tasks,
|
|
332
322
|
# there may be notified handlers from the previous section
|
ansible/plugins/action/fetch.py
CHANGED
|
@@ -192,7 +192,7 @@ class ActionModule(ActionBase):
|
|
|
192
192
|
msg="checksum mismatch", file=source, dest=dest, remote_md5sum=None,
|
|
193
193
|
checksum=new_checksum, remote_checksum=remote_checksum))
|
|
194
194
|
else:
|
|
195
|
-
result.update({'changed': True, 'md5sum': new_md5, 'dest': dest,
|
|
195
|
+
result.update({'changed': True, 'md5sum': new_md5, 'file': source, 'dest': dest,
|
|
196
196
|
'remote_md5sum': None, 'checksum': new_checksum,
|
|
197
197
|
'remote_checksum': remote_checksum})
|
|
198
198
|
else:
|
ansible/plugins/test/falsy.yml
CHANGED
|
@@ -5,7 +5,7 @@ DOCUMENTATION:
|
|
|
5
5
|
short_description: Pythonic false
|
|
6
6
|
description:
|
|
7
7
|
- This check is a more Python version of what is 'false'.
|
|
8
|
-
- It is the opposite of
|
|
8
|
+
- It is the opposite of P(ansible.builtin.truthy#test).
|
|
9
9
|
options:
|
|
10
10
|
_input:
|
|
11
11
|
description: An expression that can be expressed in a boolean context.
|
ansible/plugins/test/truthy.yml
CHANGED
|
@@ -20,5 +20,5 @@ EXAMPLES: |
|
|
|
20
20
|
thisisfalse: '{{ "" is truthy }}'
|
|
21
21
|
RETURN:
|
|
22
22
|
_value:
|
|
23
|
-
description: Returns V(True) if the condition is
|
|
23
|
+
description: Returns V(True) if the condition is "Python truthy", V(False) otherwise.
|
|
24
24
|
type: boolean
|
ansible/release.py
CHANGED
ansible/vars/manager.py
CHANGED
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
|
|
18
18
|
from __future__ import annotations
|
|
19
19
|
|
|
20
|
-
import os
|
|
21
20
|
import sys
|
|
22
21
|
import typing as t
|
|
23
22
|
|
|
@@ -447,7 +446,7 @@ class VariableManager:
|
|
|
447
446
|
"""
|
|
448
447
|
|
|
449
448
|
variables = {}
|
|
450
|
-
variables['playbook_dir'] =
|
|
449
|
+
variables['playbook_dir'] = self._loader.get_basedir()
|
|
451
450
|
variables['ansible_playbook_python'] = sys.executable
|
|
452
451
|
variables['ansible_config_file'] = C.CONFIG_FILE
|
|
453
452
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ansible-core
|
|
3
|
-
Version: 2.20.
|
|
3
|
+
Version: 2.20.0rc1
|
|
4
4
|
Summary: Radically simple IT automation
|
|
5
5
|
Author: Ansible Project
|
|
6
6
|
Project-URL: Homepage, https://ansible.com/
|
|
@@ -37,7 +37,7 @@ Requires-Dist: jinja2>=3.1.0
|
|
|
37
37
|
Requires-Dist: PyYAML>=5.1
|
|
38
38
|
Requires-Dist: cryptography
|
|
39
39
|
Requires-Dist: packaging
|
|
40
|
-
Requires-Dist: resolvelib<2.0.0,>=0.
|
|
40
|
+
Requires-Dist: resolvelib<2.0.0,>=0.8.0
|
|
41
41
|
Dynamic: license-file
|
|
42
42
|
|
|
43
43
|
[](https://pypi.org/project/ansible-core)
|