ansible-core 2.19.0b6__py3-none-any.whl → 2.19.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.
- ansible/_internal/_json/__init__.py +31 -20
- ansible/_internal/_json/_profiles/_legacy.py +1 -1
- ansible/_internal/_templating/_jinja_bits.py +46 -14
- ansible/_internal/_templating/_jinja_common.py +1 -1
- ansible/_internal/_templating/_jinja_plugins.py +5 -2
- ansible/_internal/_templating/_utils.py +2 -1
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/dump_object.py +9 -0
- ansible/cli/__init__.py +2 -2
- ansible/cli/_ssh_askpass.py +37 -30
- ansible/cli/adhoc.py +6 -3
- ansible/cli/console.py +2 -2
- ansible/cli/doc.py +2 -2
- ansible/config/base.yml +9 -6
- ansible/executor/module_common.py +9 -6
- ansible/executor/powershell/psrp_put_file.ps1 +1 -1
- ansible/executor/task_executor.py +2 -2
- ansible/executor/task_queue_manager.py +34 -70
- ansible/executor/task_result.py +1 -1
- ansible/galaxy/api.py +2 -2
- ansible/galaxy/collection/concrete_artifact_manager.py +2 -2
- ansible/galaxy/dependency_resolution/providers.py +3 -3
- ansible/inventory/group.py +6 -1
- ansible/inventory/host.py +6 -1
- ansible/module_utils/_internal/_datatag/__init__.py +6 -1
- ansible/module_utils/_internal/_deprecator.py +12 -1
- ansible/module_utils/ansible_release.py +1 -1
- ansible/module_utils/basic.py +14 -16
- ansible/module_utils/common/yaml.py +1 -1
- ansible/module_utils/csharp/Ansible.Basic.cs +1 -1
- ansible/module_utils/csharp/Ansible.Privilege.cs +2 -2
- ansible/module_utils/facts/hardware/base.py +1 -1
- ansible/module_utils/facts/other/facter.py +1 -1
- ansible/module_utils/facts/system/distribution.py +2 -2
- ansible/module_utils/powershell/Ansible.ModuleUtils.AddType.psm1 +1 -1
- ansible/module_utils/powershell/Ansible.ModuleUtils.CamelConversion.psm1 +1 -1
- ansible/module_utils/powershell/Ansible.ModuleUtils.CommandUtil.psm1 +1 -1
- ansible/module_utils/powershell/Ansible.ModuleUtils.WebRequest.psm1 +1 -1
- ansible/module_utils/urls.py +1 -1
- ansible/modules/apt.py +9 -3
- ansible/modules/assemble.py +5 -3
- ansible/modules/expect.py +5 -5
- ansible/modules/hostname.py +2 -2
- ansible/modules/pip.py +9 -11
- ansible/modules/raw.py +2 -2
- ansible/modules/stat.py +1 -1
- ansible/modules/systemd.py +1 -1
- ansible/modules/systemd_service.py +1 -1
- ansible/modules/wait_for.py +10 -3
- ansible/parsing/mod_args.py +38 -20
- ansible/parsing/vault/__init__.py +3 -3
- ansible/playbook/base.py +0 -2
- ansible/playbook/helpers.py +1 -1
- ansible/playbook/playbook_include.py +23 -57
- ansible/playbook/role/__init__.py +40 -23
- ansible/plugins/action/__init__.py +2 -2
- ansible/plugins/action/assemble.py +2 -1
- ansible/plugins/action/assert.py +2 -2
- ansible/plugins/action/script.py +5 -4
- ansible/plugins/action/template.py +1 -1
- ansible/plugins/callback/__init__.py +77 -87
- ansible/plugins/callback/default.py +0 -3
- ansible/plugins/callback/junit.py +0 -6
- ansible/plugins/connection/ssh.py +13 -6
- ansible/plugins/filter/pow.yml +1 -1
- ansible/plugins/filter/root.yml +1 -1
- ansible/plugins/filter/strftime.yml +3 -3
- ansible/plugins/filter/to_uuid.yml +1 -1
- ansible/plugins/inventory/script.py +1 -1
- ansible/plugins/loader.py +5 -0
- ansible/plugins/lookup/password.py +4 -6
- ansible/release.py +1 -1
- ansible/utils/display.py +16 -26
- ansible/utils/path.py +1 -1
- ansible/utils/vars.py +6 -2
- ansible/vars/manager.py +6 -3
- ansible/vars/reserved.py +6 -4
- {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0rc1.dist-info}/METADATA +1 -1
- {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0rc1.dist-info}/RECORD +111 -109
- ansible_test/_internal/__init__.py +5 -0
- ansible_test/_internal/ansible_util.py +1 -1
- ansible_test/_internal/classification/python.py +6 -0
- ansible_test/_internal/cli/commands/__init__.py +0 -5
- ansible_test/_internal/cli/environments.py +51 -5
- ansible_test/_internal/commands/coverage/__init__.py +1 -1
- ansible_test/_internal/commands/integration/__init__.py +18 -5
- ansible_test/_internal/commands/integration/cloud/httptester.py +1 -1
- ansible_test/_internal/commands/sanity/__init__.py +3 -1
- ansible_test/_internal/commands/sanity/integration_aliases.py +11 -0
- ansible_test/_internal/commands/shell/__init__.py +43 -4
- ansible_test/_internal/commands/units/__init__.py +4 -1
- ansible_test/_internal/config.py +21 -13
- ansible_test/_internal/debugging.py +166 -0
- ansible_test/_internal/delegation.py +21 -13
- ansible_test/_internal/host_profiles.py +197 -6
- ansible_test/_internal/inventory.py +4 -0
- ansible_test/_internal/metadata.py +94 -4
- ansible_test/_internal/processes.py +80 -0
- ansible_test/_internal/python_requirements.py +27 -0
- ansible_test/_internal/target.py +8 -0
- ansible_test/_internal/util_common.py +13 -3
- ansible_test/_util/controller/sanity/pylint/plugins/deprecated_calls.py +2 -1
- ansible_test/_util/target/injector/python.py +8 -0
- {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0rc1.dist-info}/WHEEL +0 -0
- {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0rc1.dist-info}/entry_points.txt +0 -0
- {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0rc1.dist-info}/licenses/COPYING +0 -0
- {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0rc1.dist-info}/licenses/licenses/Apache-License.txt +0 -0
- {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0rc1.dist-info}/licenses/licenses/BSD-3-Clause.txt +0 -0
- {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0rc1.dist-info}/licenses/licenses/MIT-license.txt +0 -0
- {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0rc1.dist-info}/licenses/licenses/PSF-license.txt +0 -0
- {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0rc1.dist-info}/licenses/licenses/simplified_bsd.txt +0 -0
- {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0rc1.dist-info}/top_level.txt +0 -0
ansible/utils/display.py
CHANGED
@@ -40,7 +40,6 @@ import secrets
|
|
40
40
|
import subprocess
|
41
41
|
import sys
|
42
42
|
import termios
|
43
|
-
import textwrap
|
44
43
|
import threading
|
45
44
|
import time
|
46
45
|
import tty
|
@@ -329,7 +328,6 @@ class Display(metaclass=Singleton):
|
|
329
328
|
self.noncow = C.ANSIBLE_COW_SELECTION
|
330
329
|
|
331
330
|
self.set_cowsay_info()
|
332
|
-
self._wrap_stderr = C.WRAP_STDERR
|
333
331
|
|
334
332
|
if self.b_cowsay:
|
335
333
|
try:
|
@@ -621,6 +619,12 @@ class Display(metaclass=Singleton):
|
|
621
619
|
# collections have a resolved_name but no type
|
622
620
|
collection = deprecator.resolved_name if deprecator else None
|
623
621
|
plugin_fragment = ''
|
622
|
+
elif deprecator.resolved_name == 'ansible.builtin':
|
623
|
+
# core deprecations from base classes (the API) have no plugin name, only 'ansible.builtin'
|
624
|
+
plugin_type_name = str(deprecator.type) if deprecator.type is _messages.PluginType.MODULE else f'{deprecator.type} plugin'
|
625
|
+
|
626
|
+
collection = deprecator.resolved_name
|
627
|
+
plugin_fragment = f'the {plugin_type_name} API'
|
624
628
|
else:
|
625
629
|
parts = deprecator.resolved_name.split('.')
|
626
630
|
plugin_name = parts[-1]
|
@@ -657,13 +661,6 @@ class Display(metaclass=Singleton):
|
|
657
661
|
|
658
662
|
return _join_sentences(msg, deprecation_msg)
|
659
663
|
|
660
|
-
def _wrap_message(self, msg: str, wrap_text: bool) -> str:
|
661
|
-
if wrap_text and self._wrap_stderr:
|
662
|
-
wrapped = textwrap.wrap(msg, self.columns, drop_whitespace=False)
|
663
|
-
msg = "\n".join(wrapped) + "\n"
|
664
|
-
|
665
|
-
return msg
|
666
|
-
|
667
664
|
@staticmethod
|
668
665
|
def _deduplicate(msg: str, messages: set[str]) -> bool:
|
669
666
|
"""
|
@@ -780,9 +777,6 @@ class Display(metaclass=Singleton):
|
|
780
777
|
msg = _format_message(warning, _traceback.is_traceback_enabled(_traceback.TracebackEvent.DEPRECATED))
|
781
778
|
msg = f'[DEPRECATION WARNING]: {msg}'
|
782
779
|
|
783
|
-
# DTFIX3: what should we do with wrap_message?
|
784
|
-
msg = self._wrap_message(msg=msg, wrap_text=True)
|
785
|
-
|
786
780
|
if self._deduplicate(msg, self._deprecations):
|
787
781
|
return
|
788
782
|
|
@@ -799,6 +793,8 @@ class Display(metaclass=Singleton):
|
|
799
793
|
"""Display a warning message."""
|
800
794
|
_skip_stackwalk = True
|
801
795
|
|
796
|
+
# deprecated: description='The formatted argument has no effect.' core_version='2.23'
|
797
|
+
|
802
798
|
# This is the pre-proxy half of the `warning` implementation.
|
803
799
|
# Any logic that must occur on workers needs to be implemented here.
|
804
800
|
|
@@ -818,13 +814,12 @@ class Display(metaclass=Singleton):
|
|
818
814
|
|
819
815
|
if warning_ctx := _DeferredWarningContext.current(optional=True):
|
820
816
|
warning_ctx.capture(warning)
|
821
|
-
# DTFIX3: what to do about propagating wrap_text?
|
822
817
|
return
|
823
818
|
|
824
|
-
self._warning(warning
|
819
|
+
self._warning(warning)
|
825
820
|
|
826
821
|
@_proxy
|
827
|
-
def _warning(self, warning: _messages.WarningSummary
|
822
|
+
def _warning(self, warning: _messages.WarningSummary) -> None:
|
828
823
|
"""Internal implementation detail, use `warning` instead."""
|
829
824
|
|
830
825
|
# This is the post-proxy half of the `warning` implementation.
|
@@ -836,9 +831,6 @@ class Display(metaclass=Singleton):
|
|
836
831
|
if self._deduplicate(msg, self._warns):
|
837
832
|
return
|
838
833
|
|
839
|
-
# DTFIX3: what should we do with wrap_message?
|
840
|
-
msg = self._wrap_message(msg=msg, wrap_text=wrap_text)
|
841
|
-
|
842
834
|
self.display(msg, color=C.config.get_config_value('COLOR_WARN'), stderr=True, caplevel=-2)
|
843
835
|
|
844
836
|
@_proxy
|
@@ -927,19 +919,20 @@ class Display(metaclass=Singleton):
|
|
927
919
|
warning_ctx.capture(warning)
|
928
920
|
return
|
929
921
|
|
930
|
-
self._warning(warning
|
922
|
+
self._warning(warning)
|
931
923
|
|
932
924
|
def error(self, msg: str | BaseException, wrap_text: bool = True, stderr: bool = True) -> None:
|
933
925
|
"""Display an error message."""
|
934
926
|
_skip_stackwalk = True
|
935
927
|
|
928
|
+
# deprecated: description='The wrap_text argument has no effect.' core_version='2.23'
|
929
|
+
# deprecated: description='The stderr argument has no effect.' core_version='2.23'
|
930
|
+
|
936
931
|
# This is the pre-proxy half of the `error` implementation.
|
937
932
|
# Any logic that must occur on workers needs to be implemented here.
|
938
933
|
|
939
934
|
if isinstance(msg, BaseException):
|
940
935
|
event = _error_factory.ControllerEventFactory.from_exception(msg, _traceback.is_traceback_enabled(_traceback.TracebackEvent.ERROR))
|
941
|
-
|
942
|
-
wrap_text = False
|
943
936
|
else:
|
944
937
|
event = _messages.Event(
|
945
938
|
msg=msg,
|
@@ -950,10 +943,10 @@ class Display(metaclass=Singleton):
|
|
950
943
|
event=event,
|
951
944
|
)
|
952
945
|
|
953
|
-
self._error(error,
|
946
|
+
self._error(error, stderr=True)
|
954
947
|
|
955
948
|
@_proxy
|
956
|
-
def _error(self, error: _messages.ErrorSummary,
|
949
|
+
def _error(self, error: _messages.ErrorSummary, stderr: bool) -> None:
|
957
950
|
"""Internal implementation detail, use `error` instead."""
|
958
951
|
|
959
952
|
# This is the post-proxy half of the `error` implementation.
|
@@ -965,9 +958,6 @@ class Display(metaclass=Singleton):
|
|
965
958
|
if self._deduplicate(msg, self._errors):
|
966
959
|
return
|
967
960
|
|
968
|
-
# DTFIX3: what should we do with wrap_message?
|
969
|
-
msg = self._wrap_message(msg=msg, wrap_text=wrap_text)
|
970
|
-
|
971
961
|
self.display(msg, color=C.config.get_config_value('COLOR_ERROR'), stderr=stderr, caplevel=-1)
|
972
962
|
|
973
963
|
@staticmethod
|
ansible/utils/path.py
CHANGED
@@ -102,7 +102,7 @@ def basedir(source):
|
|
102
102
|
dname = os.path.dirname(source)
|
103
103
|
|
104
104
|
if dname:
|
105
|
-
# don't follow symlinks for basedir, enables source
|
105
|
+
# don't follow symlinks for basedir, enables source reuse
|
106
106
|
dname = os.path.abspath(dname)
|
107
107
|
|
108
108
|
return to_text(dname, errors='surrogate_or_strict')
|
ansible/utils/vars.py
CHANGED
@@ -28,6 +28,7 @@ from json import dumps
|
|
28
28
|
from ansible import constants as C
|
29
29
|
from ansible import context
|
30
30
|
from ansible._internal import _json
|
31
|
+
from ansible._internal._templating import _jinja_bits
|
31
32
|
from ansible.errors import AnsibleError, AnsibleOptionsError
|
32
33
|
from ansible.module_utils.datatag import native_type_name
|
33
34
|
from ansible.module_utils.common.text.converters import to_native, to_text
|
@@ -252,6 +253,8 @@ def isidentifier(ident):
|
|
252
253
|
|
253
254
|
Originally posted at https://stackoverflow.com/a/29586366
|
254
255
|
"""
|
256
|
+
# deprecated: description='Use validate_variable_name instead.' core_version='2.23'
|
257
|
+
|
255
258
|
if not isinstance(ident, str):
|
256
259
|
return False
|
257
260
|
|
@@ -269,7 +272,7 @@ def isidentifier(ident):
|
|
269
272
|
|
270
273
|
def validate_variable_name(name: object) -> None:
|
271
274
|
"""Validate the given variable name is valid, raising an AnsibleError if it is not."""
|
272
|
-
if isinstance(name, str) and isidentifier(name):
|
275
|
+
if isinstance(name, str) and name.isidentifier() and name.isascii() and name not in _jinja_bits.JINJA_KEYWORDS:
|
273
276
|
return
|
274
277
|
|
275
278
|
if isinstance(name, (str, int, float, bool, type(None))):
|
@@ -290,7 +293,7 @@ def validate_variable_name(name: object) -> None:
|
|
290
293
|
def transform_to_native_types(
|
291
294
|
value: object,
|
292
295
|
redact: bool = True,
|
293
|
-
) ->
|
296
|
+
) -> t.Any:
|
294
297
|
"""
|
295
298
|
Recursively transform the given value to Python native types.
|
296
299
|
Potentially sensitive values such as individually vaulted variables will be redacted unless ``redact=False`` is passed.
|
@@ -303,6 +306,7 @@ def transform_to_native_types(
|
|
303
306
|
convert_custom_scalars=True,
|
304
307
|
convert_to_native_values=True,
|
305
308
|
apply_transforms=True,
|
309
|
+
visit_keys=True, # ensure that keys are also converted
|
306
310
|
encrypted_string_behavior=_json.EncryptedStringBehavior.REDACT if redact else _json.EncryptedStringBehavior.DECRYPT,
|
307
311
|
)
|
308
312
|
|
ansible/vars/manager.py
CHANGED
@@ -407,7 +407,7 @@ class VariableManager:
|
|
407
407
|
all_vars = _combine_and_track(all_vars, self._extra_vars, "extra vars")
|
408
408
|
|
409
409
|
# before we add 'reserved vars', check we didn't add any reserved vars
|
410
|
-
warn_if_reserved(all_vars
|
410
|
+
warn_if_reserved(all_vars)
|
411
411
|
|
412
412
|
# magic variables
|
413
413
|
all_vars = _combine_and_track(all_vars, magic_variables, "magic vars")
|
@@ -563,7 +563,8 @@ class VariableManager:
|
|
563
563
|
if not isinstance(facts, Mapping):
|
564
564
|
raise AnsibleAssertionError("the type of 'facts' to set for host_facts should be a Mapping but is a %s" % type(facts))
|
565
565
|
|
566
|
-
warn_if_reserved(facts
|
566
|
+
warn_if_reserved(facts)
|
567
|
+
|
567
568
|
try:
|
568
569
|
host_cache = self._fact_cache.get(host)
|
569
570
|
except KeyError:
|
@@ -587,7 +588,8 @@ class VariableManager:
|
|
587
588
|
if not isinstance(facts, Mapping):
|
588
589
|
raise AnsibleAssertionError("the type of 'facts' to set for nonpersistent_facts should be a Mapping but is a %s" % type(facts))
|
589
590
|
|
590
|
-
warn_if_reserved(facts
|
591
|
+
warn_if_reserved(facts)
|
592
|
+
|
591
593
|
try:
|
592
594
|
self._nonpersistent_fact_cache[host] |= facts
|
593
595
|
except KeyError:
|
@@ -599,6 +601,7 @@ class VariableManager:
|
|
599
601
|
"""
|
600
602
|
|
601
603
|
warn_if_reserved([varname])
|
604
|
+
|
602
605
|
if host not in self._vars_cache:
|
603
606
|
self._vars_cache[host] = dict()
|
604
607
|
|
ansible/vars/reserved.py
CHANGED
@@ -66,8 +66,7 @@ def get_reserved_names(include_private: bool = True) -> set[str]:
|
|
66
66
|
|
67
67
|
|
68
68
|
def warn_if_reserved(myvars: c.Iterable[str], additional: c.Iterable[str] | None = None) -> None:
|
69
|
-
"""
|
70
|
-
|
69
|
+
"""Issue a warning for any variable which conflicts with an internally reserved name."""
|
71
70
|
if additional is None:
|
72
71
|
reserved = _RESERVED_NAMES
|
73
72
|
else:
|
@@ -76,8 +75,11 @@ def warn_if_reserved(myvars: c.Iterable[str], additional: c.Iterable[str] | None
|
|
76
75
|
varnames = set(myvars)
|
77
76
|
varnames.discard('vars') # we add this one internally, so safe to ignore
|
78
77
|
|
79
|
-
|
80
|
-
|
78
|
+
if conflicts := varnames.intersection(reserved):
|
79
|
+
# Ensure the varname used for obj is the tagged one from myvars and not the untagged one from reserved.
|
80
|
+
# This can occur because tags do not affect value equality, and intersection can return values from either the left or right side.
|
81
|
+
for varname in (name for name in myvars if name in conflicts):
|
82
|
+
display.warning(f'Found variable using reserved name {varname!r}.', obj=varname)
|
81
83
|
|
82
84
|
|
83
85
|
def is_reserved_name(name: str) -> bool:
|