ansible-core 2.18.7rc1__py3-none-any.whl → 2.19.0__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 (757) hide show
  1. ansible/_internal/__init__.py +53 -0
  2. ansible/_internal/_ansiballz/__init__.py +0 -0
  3. ansible/_internal/_ansiballz/_builder.py +101 -0
  4. ansible/_internal/_ansiballz/_wrapper.py +262 -0
  5. ansible/_internal/_collection_proxy.py +47 -0
  6. ansible/_internal/_datatag/__init__.py +0 -0
  7. ansible/_internal/_datatag/_tags.py +130 -0
  8. ansible/_internal/_datatag/_utils.py +19 -0
  9. ansible/_internal/_datatag/_wrappers.py +33 -0
  10. ansible/_internal/_errors/__init__.py +0 -0
  11. ansible/_internal/_errors/_alarm_timeout.py +66 -0
  12. ansible/_internal/_errors/_captured.py +123 -0
  13. ansible/_internal/_errors/_error_factory.py +89 -0
  14. ansible/_internal/_errors/_error_utils.py +240 -0
  15. ansible/_internal/_errors/_handler.py +91 -0
  16. ansible/_internal/_errors/_task_timeout.py +28 -0
  17. ansible/_internal/_event_formatting.py +127 -0
  18. ansible/_internal/_json/__init__.py +214 -0
  19. ansible/_internal/_json/_legacy_encoder.py +34 -0
  20. ansible/_internal/_json/_profiles/__init__.py +0 -0
  21. ansible/_internal/_json/_profiles/_cache_persistence.py +57 -0
  22. ansible/_internal/_json/_profiles/_inventory_legacy.py +40 -0
  23. ansible/_internal/_json/_profiles/_legacy.py +189 -0
  24. ansible/_internal/_locking.py +21 -0
  25. ansible/_internal/_plugins/__init__.py +0 -0
  26. ansible/_internal/_plugins/_cache.py +57 -0
  27. ansible/_internal/_ssh/__init__.py +0 -0
  28. ansible/_internal/_ssh/_agent_launch.py +91 -0
  29. ansible/_internal/_ssh/_ssh_agent.py +619 -0
  30. ansible/_internal/_task.py +78 -0
  31. ansible/_internal/_templating/__init__.py +12 -0
  32. ansible/_internal/_templating/_access.py +86 -0
  33. ansible/_internal/_templating/_chain_templar.py +63 -0
  34. ansible/_internal/_templating/_datatag.py +95 -0
  35. ansible/_internal/_templating/_engine.py +592 -0
  36. ansible/_internal/_templating/_errors.py +28 -0
  37. ansible/_internal/_templating/_jinja_bits.py +1106 -0
  38. ansible/_internal/_templating/_jinja_common.py +323 -0
  39. ansible/_internal/_templating/_jinja_patches.py +44 -0
  40. ansible/_internal/_templating/_jinja_plugins.py +375 -0
  41. ansible/_internal/_templating/_lazy_containers.py +633 -0
  42. ansible/_internal/_templating/_marker_behaviors.py +103 -0
  43. ansible/_internal/_templating/_template_vars.py +72 -0
  44. ansible/_internal/_templating/_transform.py +70 -0
  45. ansible/_internal/_templating/_utils.py +108 -0
  46. ansible/_internal/_testing.py +26 -0
  47. ansible/_internal/_wrapt.py +1052 -0
  48. ansible/_internal/_yaml/__init__.py +0 -0
  49. ansible/_internal/_yaml/_constructor.py +240 -0
  50. ansible/_internal/_yaml/_dumper.py +70 -0
  51. ansible/_internal/_yaml/_errors.py +166 -0
  52. ansible/_internal/_yaml/_loader.py +66 -0
  53. ansible/_internal/ansible_collections/ansible/_protomatter/README.md +11 -0
  54. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/action/debug.py +36 -0
  55. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/apply_trust.py +19 -0
  56. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/dump_object.py +27 -0
  57. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/finalize.py +16 -0
  58. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/origin.py +18 -0
  59. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/python_literal_eval.py +24 -0
  60. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/python_literal_eval.yml +33 -0
  61. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/tag_names.py +16 -0
  62. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/true_type.py +17 -0
  63. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/unmask.py +49 -0
  64. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/lookup/config.py +21 -0
  65. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/lookup/config.yml +2 -0
  66. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged.py +15 -0
  67. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged.yml +19 -0
  68. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged_with.py +18 -0
  69. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged_with.yml +19 -0
  70. ansible/cli/__init__.py +93 -104
  71. ansible/cli/_ssh_askpass.py +54 -0
  72. ansible/cli/adhoc.py +20 -10
  73. ansible/cli/arguments/option_helpers.py +163 -10
  74. ansible/cli/config.py +43 -68
  75. ansible/cli/console.py +13 -11
  76. ansible/cli/doc.py +134 -77
  77. ansible/cli/galaxy.py +27 -20
  78. ansible/cli/inventory.py +28 -28
  79. ansible/cli/playbook.py +4 -12
  80. ansible/cli/pull.py +6 -3
  81. ansible/cli/scripts/ansible_connection_cli_stub.py +7 -7
  82. ansible/cli/vault.py +12 -11
  83. ansible/compat/__init__.py +2 -2
  84. ansible/compat/importlib_resources.py +9 -12
  85. ansible/config/base.yml +218 -133
  86. ansible/config/manager.py +220 -159
  87. ansible/constants.py +2 -65
  88. ansible/errors/__init__.py +350 -256
  89. ansible/executor/interpreter_discovery.py +28 -149
  90. ansible/executor/module_common.py +480 -514
  91. ansible/executor/play_iterator.py +22 -27
  92. ansible/executor/playbook_executor.py +11 -11
  93. ansible/executor/powershell/async_watchdog.ps1 +97 -102
  94. ansible/executor/powershell/async_wrapper.ps1 +204 -153
  95. ansible/executor/powershell/become_wrapper.ps1 +107 -144
  96. ansible/executor/powershell/bootstrap_wrapper.ps1 +46 -9
  97. ansible/executor/powershell/coverage_wrapper.ps1 +91 -135
  98. ansible/executor/powershell/exec_wrapper.ps1 +675 -196
  99. ansible/executor/powershell/module_manifest.py +469 -265
  100. ansible/executor/powershell/module_wrapper.ps1 +195 -186
  101. ansible/executor/powershell/powershell_expand_user.ps1 +20 -0
  102. ansible/executor/powershell/powershell_mkdtemp.ps1 +17 -0
  103. ansible/executor/powershell/psrp_fetch_file.ps1 +41 -0
  104. ansible/executor/powershell/psrp_put_file.ps1 +122 -0
  105. ansible/executor/powershell/winrm_fetch_file.ps1 +46 -0
  106. ansible/executor/powershell/winrm_put_file.ps1 +36 -0
  107. ansible/executor/process/worker.py +139 -149
  108. ansible/executor/stats.py +5 -5
  109. ansible/executor/task_executor.py +270 -297
  110. ansible/executor/task_queue_manager.py +135 -137
  111. ansible/executor/task_result.py +182 -79
  112. ansible/galaxy/__init__.py +2 -2
  113. ansible/galaxy/api.py +26 -25
  114. ansible/galaxy/collection/__init__.py +6 -14
  115. ansible/galaxy/collection/concrete_artifact_manager.py +12 -21
  116. ansible/galaxy/dependency_resolution/dataclasses.py +14 -4
  117. ansible/galaxy/dependency_resolution/providers.py +4 -4
  118. ansible/galaxy/dependency_resolution/reporters.py +81 -0
  119. ansible/galaxy/role.py +6 -10
  120. ansible/galaxy/token.py +28 -21
  121. ansible/inventory/data.py +47 -57
  122. ansible/inventory/group.py +50 -73
  123. ansible/inventory/helpers.py +9 -0
  124. ansible/inventory/host.py +37 -54
  125. ansible/inventory/manager.py +79 -34
  126. ansible/keyword_desc.yml +1 -1
  127. ansible/module_utils/_internal/__init__.py +55 -0
  128. ansible/module_utils/_internal/_ambient_context.py +58 -0
  129. ansible/module_utils/_internal/_ansiballz/__init__.py +0 -0
  130. ansible/module_utils/_internal/_ansiballz/_extensions/__init__.py +0 -0
  131. ansible/module_utils/_internal/_ansiballz/_extensions/_coverage.py +45 -0
  132. ansible/module_utils/_internal/_ansiballz/_extensions/_pydevd.py +62 -0
  133. ansible/module_utils/_internal/_ansiballz/_loader.py +81 -0
  134. ansible/module_utils/_internal/_ansiballz/_respawn.py +32 -0
  135. ansible/module_utils/_internal/_ansiballz/_respawn_wrapper.py +23 -0
  136. ansible/module_utils/_internal/_concurrent/_daemon_threading.py +1 -0
  137. ansible/module_utils/_internal/_dataclass_validation.py +217 -0
  138. ansible/module_utils/_internal/_datatag/__init__.py +961 -0
  139. ansible/module_utils/_internal/_datatag/_tags.py +16 -0
  140. ansible/module_utils/_internal/_debugging.py +31 -0
  141. ansible/module_utils/_internal/_deprecator.py +157 -0
  142. ansible/module_utils/_internal/_errors.py +101 -0
  143. ansible/module_utils/_internal/_event_utils.py +61 -0
  144. ansible/module_utils/_internal/_json/__init__.py +63 -0
  145. ansible/module_utils/_internal/_json/_legacy_encoder.py +26 -0
  146. ansible/module_utils/_internal/_json/_profiles/__init__.py +428 -0
  147. ansible/module_utils/_internal/_json/_profiles/_fallback_to_str.py +73 -0
  148. ansible/module_utils/_internal/_json/_profiles/_module_legacy_c2m.py +33 -0
  149. ansible/module_utils/_internal/_json/_profiles/_module_legacy_m2c.py +37 -0
  150. ansible/module_utils/_internal/_json/_profiles/_module_modern_c2m.py +35 -0
  151. ansible/module_utils/_internal/_json/_profiles/_module_modern_m2c.py +33 -0
  152. ansible/module_utils/_internal/_json/_profiles/_tagless.py +52 -0
  153. ansible/module_utils/_internal/_messages.py +130 -0
  154. ansible/module_utils/_internal/_patches/__init__.py +66 -0
  155. ansible/module_utils/_internal/_patches/_dataclass_annotation_patch.py +53 -0
  156. ansible/module_utils/_internal/_patches/_socket_patch.py +34 -0
  157. ansible/module_utils/_internal/_patches/_sys_intern_patch.py +34 -0
  158. ansible/module_utils/_internal/_plugin_info.py +38 -0
  159. ansible/module_utils/_internal/_stack.py +22 -0
  160. ansible/module_utils/_internal/_testing.py +0 -0
  161. ansible/module_utils/_internal/_text_utils.py +6 -0
  162. ansible/module_utils/_internal/_traceback.py +92 -0
  163. ansible/module_utils/_internal/_validation.py +14 -0
  164. ansible/module_utils/ansible_release.py +2 -2
  165. ansible/module_utils/api.py +1 -2
  166. ansible/module_utils/basic.py +303 -202
  167. ansible/module_utils/common/_utils.py +24 -28
  168. ansible/module_utils/common/arg_spec.py +8 -3
  169. ansible/module_utils/common/collections.py +7 -2
  170. ansible/module_utils/common/dict_transformations.py +2 -2
  171. ansible/module_utils/common/file.py +2 -2
  172. ansible/module_utils/common/json.py +90 -84
  173. ansible/module_utils/common/locale.py +2 -2
  174. ansible/module_utils/common/parameters.py +27 -24
  175. ansible/module_utils/common/process.py +2 -3
  176. ansible/module_utils/common/respawn.py +11 -33
  177. ansible/module_utils/common/sentinel.py +66 -0
  178. ansible/module_utils/common/sys_info.py +8 -8
  179. ansible/module_utils/common/text/converters.py +16 -37
  180. ansible/module_utils/common/validation.py +35 -24
  181. ansible/module_utils/common/warnings.py +143 -25
  182. ansible/module_utils/common/yaml.py +29 -3
  183. ansible/module_utils/compat/datetime.py +33 -21
  184. ansible/module_utils/compat/paramiko.py +21 -10
  185. ansible/module_utils/compat/typing.py +6 -5
  186. ansible/module_utils/connection.py +10 -13
  187. ansible/module_utils/csharp/Ansible.Basic.cs +15 -12
  188. ansible/module_utils/csharp/Ansible.Become.cs +1 -0
  189. ansible/module_utils/csharp/Ansible.Privilege.cs +2 -2
  190. ansible/module_utils/csharp/Ansible._Async.cs +517 -0
  191. ansible/module_utils/datatag.py +49 -0
  192. ansible/module_utils/distro/__init__.py +2 -2
  193. ansible/module_utils/facts/ansible_collector.py +4 -5
  194. ansible/module_utils/facts/collector.py +13 -14
  195. ansible/module_utils/facts/compat.py +4 -4
  196. ansible/module_utils/facts/default_collectors.py +1 -1
  197. ansible/module_utils/facts/hardware/aix.py +34 -0
  198. ansible/module_utils/facts/hardware/base.py +2 -2
  199. ansible/module_utils/facts/hardware/darwin.py +1 -3
  200. ansible/module_utils/facts/hardware/freebsd.py +2 -2
  201. ansible/module_utils/facts/hardware/linux.py +5 -5
  202. ansible/module_utils/facts/namespace.py +1 -1
  203. ansible/module_utils/facts/network/base.py +1 -1
  204. ansible/module_utils/facts/network/fc_wwn.py +1 -2
  205. ansible/module_utils/facts/network/iscsi.py +1 -2
  206. ansible/module_utils/facts/network/nvme.py +1 -2
  207. ansible/module_utils/facts/other/facter.py +2 -3
  208. ansible/module_utils/facts/other/ohai.py +2 -3
  209. ansible/module_utils/facts/sysctl.py +4 -6
  210. ansible/module_utils/facts/system/apparmor.py +1 -2
  211. ansible/module_utils/facts/system/caps.py +3 -3
  212. ansible/module_utils/facts/system/chroot.py +1 -2
  213. ansible/module_utils/facts/system/cmdline.py +1 -2
  214. ansible/module_utils/facts/system/date_time.py +5 -3
  215. ansible/module_utils/facts/system/distribution.py +27 -13
  216. ansible/module_utils/facts/system/dns.py +1 -1
  217. ansible/module_utils/facts/system/env.py +1 -2
  218. ansible/module_utils/facts/system/fips.py +7 -20
  219. ansible/module_utils/facts/system/loadavg.py +1 -2
  220. ansible/module_utils/facts/system/local.py +2 -3
  221. ansible/module_utils/facts/system/lsb.py +1 -2
  222. ansible/module_utils/facts/system/pkg_mgr.py +1 -2
  223. ansible/module_utils/facts/system/platform.py +1 -2
  224. ansible/module_utils/facts/system/python.py +1 -2
  225. ansible/module_utils/facts/system/selinux.py +1 -1
  226. ansible/module_utils/facts/system/service_mgr.py +1 -2
  227. ansible/module_utils/facts/system/ssh_pub_keys.py +1 -1
  228. ansible/module_utils/facts/system/systemd.py +1 -1
  229. ansible/module_utils/facts/system/user.py +1 -2
  230. ansible/module_utils/facts/utils.py +3 -3
  231. ansible/module_utils/facts/virtual/base.py +1 -1
  232. ansible/module_utils/facts/virtual/linux.py +3 -3
  233. ansible/module_utils/facts/virtual/sunos.py +3 -15
  234. ansible/module_utils/facts/virtual/sysctl.py +3 -16
  235. ansible/module_utils/json_utils.py +2 -2
  236. ansible/module_utils/parsing/convert_bool.py +7 -1
  237. ansible/module_utils/powershell/Ansible.ModuleUtils.AddType.psm1 +1 -1
  238. ansible/module_utils/powershell/Ansible.ModuleUtils.CamelConversion.psm1 +1 -1
  239. ansible/module_utils/powershell/Ansible.ModuleUtils.CommandUtil.psm1 +1 -1
  240. ansible/module_utils/powershell/Ansible.ModuleUtils.WebRequest.psm1 +1 -1
  241. ansible/module_utils/service.py +21 -31
  242. ansible/module_utils/splitter.py +7 -7
  243. ansible/module_utils/testing.py +31 -0
  244. ansible/module_utils/urls.py +64 -35
  245. ansible/modules/add_host.py +4 -4
  246. ansible/modules/apt.py +69 -49
  247. ansible/modules/apt_key.py +19 -12
  248. ansible/modules/apt_repository.py +32 -51
  249. ansible/modules/assemble.py +16 -14
  250. ansible/modules/assert.py +4 -4
  251. ansible/modules/async_status.py +24 -24
  252. ansible/modules/async_wrapper.py +20 -25
  253. ansible/modules/blockinfile.py +6 -7
  254. ansible/modules/command.py +13 -20
  255. ansible/modules/copy.py +60 -147
  256. ansible/modules/cron.py +24 -21
  257. ansible/modules/deb822_repository.py +8 -9
  258. ansible/modules/debconf.py +5 -5
  259. ansible/modules/debug.py +4 -4
  260. ansible/modules/dnf.py +8 -8
  261. ansible/modules/dnf5.py +39 -13
  262. ansible/modules/dpkg_selections.py +4 -4
  263. ansible/modules/expect.py +13 -15
  264. ansible/modules/fail.py +4 -4
  265. ansible/modules/fetch.py +4 -4
  266. ansible/modules/file.py +184 -144
  267. ansible/modules/find.py +22 -20
  268. ansible/modules/gather_facts.py +3 -3
  269. ansible/modules/get_url.py +77 -54
  270. ansible/modules/getent.py +7 -9
  271. ansible/modules/git.py +38 -38
  272. ansible/modules/group.py +6 -6
  273. ansible/modules/group_by.py +4 -4
  274. ansible/modules/hostname.py +15 -32
  275. ansible/modules/import_playbook.py +6 -6
  276. ansible/modules/import_role.py +6 -6
  277. ansible/modules/import_tasks.py +6 -6
  278. ansible/modules/include_role.py +6 -6
  279. ansible/modules/include_tasks.py +6 -6
  280. ansible/modules/include_vars.py +6 -6
  281. ansible/modules/iptables.py +86 -73
  282. ansible/modules/known_hosts.py +22 -24
  283. ansible/modules/lineinfile.py +5 -5
  284. ansible/modules/meta.py +4 -4
  285. ansible/modules/mount_facts.py +2 -2
  286. ansible/modules/package.py +10 -4
  287. ansible/modules/package_facts.py +22 -10
  288. ansible/modules/pause.py +6 -6
  289. ansible/modules/ping.py +6 -6
  290. ansible/modules/pip.py +21 -26
  291. ansible/modules/raw.py +6 -6
  292. ansible/modules/reboot.py +6 -6
  293. ansible/modules/replace.py +10 -14
  294. ansible/modules/rpm_key.py +7 -8
  295. ansible/modules/script.py +4 -4
  296. ansible/modules/service.py +10 -17
  297. ansible/modules/service_facts.py +87 -10
  298. ansible/modules/set_fact.py +5 -5
  299. ansible/modules/set_stats.py +4 -4
  300. ansible/modules/setup.py +2 -2
  301. ansible/modules/shell.py +6 -6
  302. ansible/modules/slurp.py +16 -19
  303. ansible/modules/stat.py +15 -31
  304. ansible/modules/subversion.py +15 -15
  305. ansible/modules/systemd.py +7 -7
  306. ansible/modules/systemd_service.py +7 -7
  307. ansible/modules/sysvinit.py +9 -9
  308. ansible/modules/tempfile.py +5 -6
  309. ansible/modules/template.py +6 -6
  310. ansible/modules/unarchive.py +38 -17
  311. ansible/modules/uri.py +33 -26
  312. ansible/modules/user.py +45 -32
  313. ansible/modules/validate_argument_spec.py +10 -7
  314. ansible/modules/wait_for.py +70 -60
  315. ansible/modules/wait_for_connection.py +6 -6
  316. ansible/modules/yum_repository.py +10 -9
  317. ansible/parsing/ajson.py +17 -37
  318. ansible/parsing/dataloader.py +99 -54
  319. ansible/parsing/mod_args.py +62 -60
  320. ansible/parsing/plugin_docs.py +21 -86
  321. ansible/parsing/quoting.py +1 -1
  322. ansible/parsing/splitter.py +27 -12
  323. ansible/parsing/utils/addresses.py +24 -24
  324. ansible/parsing/utils/jsonify.py +5 -1
  325. ansible/parsing/utils/yaml.py +32 -61
  326. ansible/parsing/vault/__init__.py +327 -99
  327. ansible/parsing/yaml/__init__.py +0 -18
  328. ansible/parsing/yaml/dumper.py +6 -120
  329. ansible/parsing/yaml/loader.py +6 -39
  330. ansible/parsing/yaml/objects.py +43 -335
  331. ansible/playbook/__init__.py +1 -1
  332. ansible/playbook/attribute.py +8 -3
  333. ansible/playbook/base.py +187 -134
  334. ansible/playbook/block.py +26 -24
  335. ansible/playbook/collectionsearch.py +1 -15
  336. ansible/playbook/conditional.py +3 -77
  337. ansible/playbook/handler.py +8 -2
  338. ansible/playbook/helpers.py +41 -53
  339. ansible/playbook/included_file.py +32 -26
  340. ansible/playbook/loop_control.py +2 -2
  341. ansible/playbook/play.py +85 -44
  342. ansible/playbook/play_context.py +14 -17
  343. ansible/playbook/playbook_include.py +27 -62
  344. ansible/playbook/role/__init__.py +64 -49
  345. ansible/playbook/role/definition.py +15 -17
  346. ansible/playbook/role/include.py +2 -4
  347. ansible/playbook/role/metadata.py +10 -11
  348. ansible/playbook/role_include.py +3 -3
  349. ansible/playbook/taggable.py +28 -12
  350. ansible/playbook/task.py +192 -121
  351. ansible/playbook/task_include.py +5 -5
  352. ansible/plugins/__init__.py +58 -26
  353. ansible/plugins/action/__init__.py +188 -186
  354. ansible/plugins/action/add_host.py +2 -2
  355. ansible/plugins/action/assemble.py +11 -18
  356. ansible/plugins/action/assert.py +55 -67
  357. ansible/plugins/action/async_status.py +7 -2
  358. ansible/plugins/action/copy.py +14 -17
  359. ansible/plugins/action/debug.py +37 -31
  360. ansible/plugins/action/dnf.py +3 -4
  361. ansible/plugins/action/fail.py +1 -1
  362. ansible/plugins/action/fetch.py +7 -8
  363. ansible/plugins/action/gather_facts.py +13 -14
  364. ansible/plugins/action/group_by.py +1 -1
  365. ansible/plugins/action/include_vars.py +10 -11
  366. ansible/plugins/action/package.py +8 -14
  367. ansible/plugins/action/pause.py +2 -2
  368. ansible/plugins/action/script.py +27 -38
  369. ansible/plugins/action/service.py +9 -18
  370. ansible/plugins/action/set_fact.py +3 -12
  371. ansible/plugins/action/set_stats.py +3 -8
  372. ansible/plugins/action/template.py +47 -67
  373. ansible/plugins/action/unarchive.py +6 -16
  374. ansible/plugins/action/uri.py +9 -20
  375. ansible/plugins/action/validate_argument_spec.py +5 -5
  376. ansible/plugins/action/wait_for_connection.py +1 -1
  377. ansible/plugins/become/__init__.py +31 -8
  378. ansible/plugins/become/runas.py +71 -0
  379. ansible/plugins/become/su.py +13 -8
  380. ansible/plugins/become/sudo.py +19 -0
  381. ansible/plugins/cache/__init__.py +52 -63
  382. ansible/plugins/cache/base.py +8 -0
  383. ansible/plugins/cache/jsonfile.py +10 -16
  384. ansible/plugins/cache/memory.py +6 -12
  385. ansible/plugins/callback/__init__.py +294 -201
  386. ansible/plugins/callback/default.py +99 -95
  387. ansible/plugins/callback/junit.py +44 -43
  388. ansible/plugins/callback/minimal.py +28 -25
  389. ansible/plugins/callback/oneline.py +34 -21
  390. ansible/plugins/callback/tree.py +27 -16
  391. ansible/plugins/connection/__init__.py +47 -34
  392. ansible/plugins/connection/local.py +156 -60
  393. ansible/plugins/connection/paramiko_ssh.py +34 -24
  394. ansible/plugins/connection/psrp.py +76 -165
  395. ansible/plugins/connection/ssh.py +326 -86
  396. ansible/plugins/connection/winrm.py +62 -141
  397. ansible/plugins/doc_fragments/action_common_attributes.py +14 -14
  398. ansible/plugins/doc_fragments/action_core.py +6 -6
  399. ansible/plugins/doc_fragments/backup.py +2 -2
  400. ansible/plugins/doc_fragments/checksum_common.py +27 -0
  401. ansible/plugins/doc_fragments/constructed.py +8 -4
  402. ansible/plugins/doc_fragments/decrypt.py +2 -2
  403. ansible/plugins/doc_fragments/default_callback.py +2 -2
  404. ansible/plugins/doc_fragments/files.py +2 -2
  405. ansible/plugins/doc_fragments/inventory_cache.py +2 -2
  406. ansible/plugins/doc_fragments/result_format_callback.py +2 -2
  407. ansible/plugins/doc_fragments/return_common.py +2 -2
  408. ansible/plugins/doc_fragments/template_common.py +4 -4
  409. ansible/plugins/doc_fragments/url.py +17 -1
  410. ansible/plugins/doc_fragments/url_windows.py +2 -2
  411. ansible/plugins/doc_fragments/validate.py +2 -2
  412. ansible/plugins/doc_fragments/vars_plugin_staging.py +2 -2
  413. ansible/plugins/filter/__init__.py +6 -2
  414. ansible/plugins/filter/b64decode.yml +22 -0
  415. ansible/plugins/filter/b64encode.yml +22 -0
  416. ansible/plugins/filter/bool.yml +11 -4
  417. ansible/plugins/filter/core.py +245 -120
  418. ansible/plugins/filter/encryption.py +42 -34
  419. ansible/plugins/filter/flatten.yml +3 -2
  420. ansible/plugins/filter/human_to_bytes.yml +1 -1
  421. ansible/plugins/filter/mathstuff.py +30 -37
  422. ansible/plugins/filter/password_hash.yml +8 -0
  423. ansible/plugins/filter/pow.yml +1 -1
  424. ansible/plugins/filter/regex_search.yml +1 -4
  425. ansible/plugins/filter/root.yml +1 -1
  426. ansible/plugins/filter/split.yml +1 -1
  427. ansible/plugins/filter/strftime.yml +3 -3
  428. ansible/plugins/filter/to_nice_yaml.yml +0 -4
  429. ansible/plugins/filter/to_uuid.yml +1 -1
  430. ansible/plugins/filter/to_yaml.yml +0 -4
  431. ansible/plugins/filter/unvault.yml +1 -1
  432. ansible/plugins/filter/urls.py +1 -1
  433. ansible/plugins/filter/urlsplit.py +8 -9
  434. ansible/plugins/filter/vault.yml +14 -9
  435. ansible/plugins/filter/win_basename.yml +6 -1
  436. ansible/plugins/filter/win_dirname.yml +5 -0
  437. ansible/plugins/inventory/__init__.py +107 -86
  438. ansible/plugins/inventory/advanced_host_list.py +7 -5
  439. ansible/plugins/inventory/auto.py +11 -4
  440. ansible/plugins/inventory/constructed.py +21 -24
  441. ansible/plugins/inventory/generator.py +16 -11
  442. ansible/plugins/inventory/host_list.py +7 -5
  443. ansible/plugins/inventory/ini.py +78 -44
  444. ansible/plugins/inventory/script.py +190 -120
  445. ansible/plugins/inventory/toml.py +16 -126
  446. ansible/plugins/inventory/yaml.py +10 -8
  447. ansible/plugins/list.py +72 -19
  448. ansible/plugins/loader.py +383 -198
  449. ansible/plugins/lookup/__init__.py +21 -4
  450. ansible/plugins/lookup/config.py +21 -35
  451. ansible/plugins/lookup/csvfile.py +19 -73
  452. ansible/plugins/lookup/dict.py +1 -6
  453. ansible/plugins/lookup/env.py +12 -9
  454. ansible/plugins/lookup/file.py +5 -8
  455. ansible/plugins/lookup/first_found.py +87 -55
  456. ansible/plugins/lookup/indexed_items.py +1 -10
  457. ansible/plugins/lookup/ini.py +14 -13
  458. ansible/plugins/lookup/items.py +1 -1
  459. ansible/plugins/lookup/lines.py +8 -1
  460. ansible/plugins/lookup/list.py +1 -1
  461. ansible/plugins/lookup/nested.py +2 -18
  462. ansible/plugins/lookup/password.py +5 -5
  463. ansible/plugins/lookup/pipe.py +5 -7
  464. ansible/plugins/lookup/sequence.py +18 -8
  465. ansible/plugins/lookup/subelements.py +1 -4
  466. ansible/plugins/lookup/template.py +47 -36
  467. ansible/plugins/lookup/together.py +0 -12
  468. ansible/plugins/lookup/unvault.py +1 -5
  469. ansible/plugins/lookup/url.py +4 -10
  470. ansible/plugins/lookup/vars.py +16 -24
  471. ansible/plugins/shell/__init__.py +58 -4
  472. ansible/plugins/shell/cmd.py +2 -2
  473. ansible/plugins/shell/powershell.py +106 -31
  474. ansible/plugins/shell/sh.py +13 -7
  475. ansible/plugins/strategy/__init__.py +168 -193
  476. ansible/plugins/strategy/debug.py +2 -2
  477. ansible/plugins/strategy/free.py +16 -31
  478. ansible/plugins/strategy/host_pinned.py +2 -2
  479. ansible/plugins/strategy/linear.py +41 -41
  480. ansible/plugins/terminal/__init__.py +4 -4
  481. ansible/plugins/test/__init__.py +7 -2
  482. ansible/plugins/test/core.py +75 -35
  483. ansible/plugins/test/files.py +1 -1
  484. ansible/plugins/test/finished.yml +1 -1
  485. ansible/plugins/test/mathstuff.py +3 -3
  486. ansible/plugins/test/uri.py +5 -8
  487. ansible/plugins/vars/host_group_vars.py +7 -14
  488. ansible/release.py +2 -2
  489. ansible/template/__init__.py +353 -943
  490. ansible/utils/__init__.py +0 -18
  491. ansible/utils/collection_loader/__init__.py +54 -5
  492. ansible/utils/collection_loader/_collection_config.py +5 -6
  493. ansible/utils/collection_loader/_collection_finder.py +82 -96
  494. ansible/utils/collection_loader/_collection_meta.py +15 -8
  495. ansible/utils/display.py +485 -73
  496. ansible/utils/encrypt.py +27 -19
  497. ansible/utils/fqcn.py +2 -2
  498. ansible/utils/galaxy.py +2 -2
  499. ansible/utils/hashing.py +8 -10
  500. ansible/utils/helpers.py +2 -2
  501. ansible/utils/listify.py +10 -8
  502. ansible/utils/lock.py +2 -2
  503. ansible/utils/path.py +10 -12
  504. ansible/utils/plugin_docs.py +16 -14
  505. ansible/utils/py3compat.py +2 -7
  506. ansible/utils/sentinel.py +4 -62
  507. ansible/utils/singleton.py +2 -0
  508. ansible/utils/ssh_functions.py +6 -2
  509. ansible/utils/unsafe_proxy.py +23 -332
  510. ansible/utils/vars.py +55 -8
  511. ansible/utils/version.py +2 -2
  512. ansible/vars/clean.py +5 -5
  513. ansible/vars/hostvars.py +60 -90
  514. ansible/vars/manager.py +220 -285
  515. ansible/vars/plugins.py +4 -4
  516. ansible/vars/reserved.py +13 -12
  517. {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/METADATA +4 -3
  518. ansible_core-2.19.0.dist-info/RECORD +1097 -0
  519. ansible_core-2.19.0.dist-info/licenses/licenses/BSD-3-Clause.txt +28 -0
  520. ansible_test/_data/completion/docker.txt +7 -7
  521. ansible_test/_data/completion/remote.txt +6 -6
  522. ansible_test/_data/completion/windows.txt +1 -0
  523. ansible_test/_data/requirements/ansible.txt +2 -2
  524. ansible_test/_data/requirements/sanity.ansible-doc.txt +3 -3
  525. ansible_test/_data/requirements/sanity.changelog.txt +2 -2
  526. ansible_test/_data/requirements/sanity.import.plugin.txt +2 -2
  527. ansible_test/_data/requirements/sanity.pep8.txt +1 -1
  528. ansible_test/_data/requirements/sanity.pylint.txt +5 -5
  529. ansible_test/_data/requirements/sanity.validate-modules.txt +2 -2
  530. ansible_test/_data/requirements/sanity.yamllint.txt +1 -1
  531. ansible_test/_data/requirements/units.txt +1 -0
  532. ansible_test/_internal/__init__.py +6 -0
  533. ansible_test/_internal/ansible_util.py +3 -1
  534. ansible_test/_internal/become.py +1 -0
  535. ansible_test/_internal/bootstrap.py +1 -0
  536. ansible_test/_internal/cache.py +1 -0
  537. ansible_test/_internal/cgroup.py +1 -0
  538. ansible_test/_internal/ci/__init__.py +1 -0
  539. ansible_test/_internal/ci/azp.py +1 -0
  540. ansible_test/_internal/ci/local.py +1 -0
  541. ansible_test/_internal/classification/__init__.py +1 -0
  542. ansible_test/_internal/classification/common.py +1 -0
  543. ansible_test/_internal/classification/csharp.py +1 -0
  544. ansible_test/_internal/classification/powershell.py +1 -0
  545. ansible_test/_internal/classification/python.py +1 -0
  546. ansible_test/_internal/cli/__init__.py +1 -0
  547. ansible_test/_internal/cli/actions.py +1 -0
  548. ansible_test/_internal/cli/argparsing/__init__.py +1 -0
  549. ansible_test/_internal/cli/argparsing/actions.py +1 -0
  550. ansible_test/_internal/cli/argparsing/argcompletion.py +1 -0
  551. ansible_test/_internal/cli/argparsing/parsers.py +1 -0
  552. ansible_test/_internal/cli/commands/__init__.py +11 -5
  553. ansible_test/_internal/cli/commands/coverage/__init__.py +1 -0
  554. ansible_test/_internal/cli/commands/coverage/analyze/__init__.py +1 -0
  555. ansible_test/_internal/cli/commands/coverage/analyze/targets/__init__.py +1 -0
  556. ansible_test/_internal/cli/commands/coverage/analyze/targets/combine.py +1 -0
  557. ansible_test/_internal/cli/commands/coverage/analyze/targets/expand.py +1 -0
  558. ansible_test/_internal/cli/commands/coverage/analyze/targets/filter.py +1 -0
  559. ansible_test/_internal/cli/commands/coverage/analyze/targets/generate.py +1 -0
  560. ansible_test/_internal/cli/commands/coverage/analyze/targets/missing.py +1 -0
  561. ansible_test/_internal/cli/commands/coverage/combine.py +1 -0
  562. ansible_test/_internal/cli/commands/coverage/erase.py +1 -0
  563. ansible_test/_internal/cli/commands/coverage/html.py +1 -0
  564. ansible_test/_internal/cli/commands/coverage/report.py +1 -0
  565. ansible_test/_internal/cli/commands/coverage/xml.py +1 -0
  566. ansible_test/_internal/cli/commands/env.py +1 -0
  567. ansible_test/_internal/cli/commands/integration/__init__.py +1 -0
  568. ansible_test/_internal/cli/commands/integration/network.py +1 -0
  569. ansible_test/_internal/cli/commands/integration/posix.py +1 -0
  570. ansible_test/_internal/cli/commands/integration/windows.py +1 -0
  571. ansible_test/_internal/cli/commands/sanity.py +9 -0
  572. ansible_test/_internal/cli/commands/shell.py +1 -0
  573. ansible_test/_internal/cli/commands/units.py +1 -0
  574. ansible_test/_internal/cli/compat.py +1 -0
  575. ansible_test/_internal/cli/completers.py +1 -0
  576. ansible_test/_internal/cli/converters.py +1 -0
  577. ansible_test/_internal/cli/environments.py +52 -5
  578. ansible_test/_internal/cli/epilog.py +1 -0
  579. ansible_test/_internal/cli/parsers/__init__.py +1 -0
  580. ansible_test/_internal/cli/parsers/base_argument_parsers.py +1 -0
  581. ansible_test/_internal/cli/parsers/helpers.py +1 -0
  582. ansible_test/_internal/cli/parsers/host_config_parsers.py +1 -0
  583. ansible_test/_internal/cli/parsers/key_value_parsers.py +1 -0
  584. ansible_test/_internal/cli/parsers/value_parsers.py +1 -0
  585. ansible_test/_internal/commands/__init__.py +1 -0
  586. ansible_test/_internal/commands/coverage/__init__.py +3 -2
  587. ansible_test/_internal/commands/coverage/analyze/__init__.py +1 -0
  588. ansible_test/_internal/commands/coverage/analyze/targets/__init__.py +1 -0
  589. ansible_test/_internal/commands/coverage/analyze/targets/combine.py +1 -0
  590. ansible_test/_internal/commands/coverage/analyze/targets/expand.py +1 -0
  591. ansible_test/_internal/commands/coverage/analyze/targets/filter.py +1 -0
  592. ansible_test/_internal/commands/coverage/analyze/targets/generate.py +1 -0
  593. ansible_test/_internal/commands/coverage/analyze/targets/missing.py +1 -0
  594. ansible_test/_internal/commands/coverage/combine.py +2 -1
  595. ansible_test/_internal/commands/coverage/erase.py +1 -0
  596. ansible_test/_internal/commands/coverage/html.py +1 -0
  597. ansible_test/_internal/commands/coverage/report.py +1 -0
  598. ansible_test/_internal/commands/coverage/xml.py +1 -0
  599. ansible_test/_internal/commands/env/__init__.py +2 -0
  600. ansible_test/_internal/commands/integration/__init__.py +22 -5
  601. ansible_test/_internal/commands/integration/cloud/__init__.py +1 -0
  602. ansible_test/_internal/commands/integration/cloud/acme.py +2 -1
  603. ansible_test/_internal/commands/integration/cloud/aws.py +1 -0
  604. ansible_test/_internal/commands/integration/cloud/azure.py +1 -0
  605. ansible_test/_internal/commands/integration/cloud/cs.py +1 -0
  606. ansible_test/_internal/commands/integration/cloud/digitalocean.py +1 -0
  607. ansible_test/_internal/commands/integration/cloud/galaxy.py +3 -2
  608. ansible_test/_internal/commands/integration/cloud/hcloud.py +1 -0
  609. ansible_test/_internal/commands/integration/cloud/httptester.py +3 -2
  610. ansible_test/_internal/commands/integration/cloud/nios.py +2 -1
  611. ansible_test/_internal/commands/integration/cloud/opennebula.py +1 -0
  612. ansible_test/_internal/commands/integration/cloud/openshift.py +1 -0
  613. ansible_test/_internal/commands/integration/cloud/scaleway.py +1 -0
  614. ansible_test/_internal/commands/integration/cloud/vcenter.py +1 -0
  615. ansible_test/_internal/commands/integration/cloud/vultr.py +1 -0
  616. ansible_test/_internal/commands/integration/coverage.py +8 -2
  617. ansible_test/_internal/commands/integration/filters.py +1 -0
  618. ansible_test/_internal/commands/integration/network.py +1 -0
  619. ansible_test/_internal/commands/integration/posix.py +1 -0
  620. ansible_test/_internal/commands/integration/windows.py +1 -0
  621. ansible_test/_internal/commands/sanity/__init__.py +19 -2
  622. ansible_test/_internal/commands/sanity/ansible_doc.py +1 -0
  623. ansible_test/_internal/commands/sanity/bin_symlinks.py +1 -0
  624. ansible_test/_internal/commands/sanity/compile.py +1 -0
  625. ansible_test/_internal/commands/sanity/ignores.py +1 -0
  626. ansible_test/_internal/commands/sanity/import.py +1 -0
  627. ansible_test/_internal/commands/sanity/integration_aliases.py +12 -0
  628. ansible_test/_internal/commands/sanity/pep8.py +1 -0
  629. ansible_test/_internal/commands/sanity/pslint.py +1 -0
  630. ansible_test/_internal/commands/sanity/pylint.py +25 -26
  631. ansible_test/_internal/commands/sanity/shellcheck.py +1 -0
  632. ansible_test/_internal/commands/sanity/validate_modules.py +1 -0
  633. ansible_test/_internal/commands/sanity/yamllint.py +1 -0
  634. ansible_test/_internal/commands/shell/__init__.py +44 -4
  635. ansible_test/_internal/commands/units/__init__.py +5 -1
  636. ansible_test/_internal/compat/__init__.py +1 -0
  637. ansible_test/_internal/compat/packaging.py +1 -0
  638. ansible_test/_internal/compat/yaml.py +1 -0
  639. ansible_test/_internal/completion.py +1 -0
  640. ansible_test/_internal/config.py +23 -13
  641. ansible_test/_internal/connections.py +1 -0
  642. ansible_test/_internal/constants.py +1 -0
  643. ansible_test/_internal/containers.py +1 -0
  644. ansible_test/_internal/content_config.py +1 -0
  645. ansible_test/_internal/core_ci.py +1 -0
  646. ansible_test/_internal/coverage_util.py +11 -10
  647. ansible_test/_internal/data.py +1 -0
  648. ansible_test/_internal/debugging.py +166 -0
  649. ansible_test/_internal/delegation.py +22 -13
  650. ansible_test/_internal/dev/__init__.py +1 -0
  651. ansible_test/_internal/dev/container_probe.py +1 -0
  652. ansible_test/_internal/diff.py +3 -2
  653. ansible_test/_internal/docker_util.py +2 -1
  654. ansible_test/_internal/encoding.py +1 -0
  655. ansible_test/_internal/executor.py +1 -0
  656. ansible_test/_internal/git.py +1 -0
  657. ansible_test/_internal/host_configs.py +1 -0
  658. ansible_test/_internal/host_profiles.py +260 -16
  659. ansible_test/_internal/http.py +1 -0
  660. ansible_test/_internal/init.py +1 -0
  661. ansible_test/_internal/inventory.py +39 -3
  662. ansible_test/_internal/io.py +1 -0
  663. ansible_test/_internal/metadata.py +95 -4
  664. ansible_test/_internal/payload.py +1 -0
  665. ansible_test/_internal/processes.py +80 -0
  666. ansible_test/_internal/provider/__init__.py +1 -0
  667. ansible_test/_internal/provider/layout/__init__.py +1 -0
  668. ansible_test/_internal/provider/layout/ansible.py +1 -0
  669. ansible_test/_internal/provider/layout/collection.py +1 -0
  670. ansible_test/_internal/provider/layout/unsupported.py +1 -0
  671. ansible_test/_internal/provider/source/__init__.py +1 -0
  672. ansible_test/_internal/provider/source/git.py +1 -0
  673. ansible_test/_internal/provider/source/installed.py +1 -0
  674. ansible_test/_internal/provider/source/unsupported.py +1 -0
  675. ansible_test/_internal/provider/source/unversioned.py +1 -0
  676. ansible_test/_internal/provisioning.py +11 -4
  677. ansible_test/_internal/pypi_proxy.py +6 -5
  678. ansible_test/_internal/python_requirements.py +28 -0
  679. ansible_test/_internal/ssh.py +2 -5
  680. ansible_test/_internal/target.py +9 -0
  681. ansible_test/_internal/test.py +3 -2
  682. ansible_test/_internal/thread.py +3 -1
  683. ansible_test/_internal/timeout.py +2 -1
  684. ansible_test/_internal/util.py +41 -12
  685. ansible_test/_internal/util_common.py +18 -5
  686. ansible_test/_internal/venv.py +1 -0
  687. ansible_test/_util/controller/sanity/code-smell/action-plugin-docs.py +1 -0
  688. ansible_test/_util/controller/sanity/code-smell/changelog/sphinx.py +1 -0
  689. ansible_test/_util/controller/sanity/code-smell/changelog.py +1 -0
  690. ansible_test/_util/controller/sanity/code-smell/empty-init.py +1 -0
  691. ansible_test/_util/controller/sanity/code-smell/line-endings.py +1 -0
  692. ansible_test/_util/controller/sanity/code-smell/no-assert.py +1 -0
  693. ansible_test/_util/controller/sanity/code-smell/no-get-exception.py +1 -0
  694. ansible_test/_util/controller/sanity/code-smell/no-illegal-filenames.py +1 -0
  695. ansible_test/_util/controller/sanity/code-smell/no-smart-quotes.py +1 -0
  696. ansible_test/_util/controller/sanity/code-smell/replace-urlopen.py +1 -0
  697. ansible_test/_util/controller/sanity/code-smell/runtime-metadata.py +28 -1
  698. ansible_test/_util/controller/sanity/code-smell/shebang.py +1 -0
  699. ansible_test/_util/controller/sanity/code-smell/symlinks.py +1 -0
  700. ansible_test/_util/controller/sanity/code-smell/use-argspec-type-path.py +1 -0
  701. ansible_test/_util/controller/sanity/code-smell/use-compat-six.py +1 -0
  702. ansible_test/_util/controller/sanity/integration-aliases/yaml_to_json.py +2 -1
  703. ansible_test/_util/controller/sanity/pep8/current-ignore.txt +4 -0
  704. ansible_test/_util/controller/sanity/pylint/config/ansible-test-target.cfg +8 -5
  705. ansible_test/_util/controller/sanity/pylint/config/ansible-test.cfg +8 -5
  706. ansible_test/_util/controller/sanity/pylint/config/code-smell.cfg +8 -5
  707. ansible_test/_util/controller/sanity/pylint/config/collection.cfg +4 -5
  708. ansible_test/_util/controller/sanity/pylint/config/default.cfg +8 -7
  709. ansible_test/_util/controller/sanity/pylint/plugins/deprecated_calls.py +541 -0
  710. ansible_test/_util/controller/sanity/pylint/plugins/deprecated_comment.py +137 -0
  711. ansible_test/_util/controller/sanity/pylint/plugins/hide_unraisable.py +1 -0
  712. ansible_test/_util/controller/sanity/pylint/plugins/string_format.py +1 -8
  713. ansible_test/_util/controller/sanity/pylint/plugins/unwanted.py +1 -8
  714. ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py +55 -28
  715. ansible_test/_util/controller/sanity/validate-modules/validate_modules/module_args.py +12 -5
  716. ansible_test/_util/controller/sanity/validate-modules/validate_modules/schema.py +13 -2
  717. ansible_test/_util/controller/sanity/validate-modules/validate_modules/utils.py +1 -0
  718. ansible_test/_util/controller/sanity/yamllint/yamllinter.py +35 -17
  719. ansible_test/_util/controller/tools/collection_detail.py +1 -0
  720. ansible_test/_util/controller/tools/yaml_to_json.py +2 -1
  721. ansible_test/_util/target/injector/python.py +8 -0
  722. ansible_test/_util/target/pytest/plugins/ansible_forked.py +6 -1
  723. ansible_test/_util/target/pytest/plugins/ansible_pytest_collections.py +2 -1
  724. ansible_test/_util/target/pytest/plugins/ansible_pytest_coverage.py +1 -0
  725. ansible_test/_util/target/sanity/compile/compile.py +1 -0
  726. ansible_test/_util/target/sanity/import/importer.py +15 -16
  727. ansible_test/_util/target/setup/bootstrap.sh +9 -20
  728. ansible_test/_util/target/setup/probe_cgroups.py +1 -0
  729. ansible_test/_util/target/setup/quiet_pip.py +1 -0
  730. ansible_test/_util/target/setup/requirements.py +38 -36
  731. ansible_test/_util/target/tools/virtualenvcheck.py +2 -1
  732. ansible_test/_util/target/tools/yamlcheck.py +2 -1
  733. ansible/compat/selectors.py +0 -32
  734. ansible/errors/yaml_strings.py +0 -138
  735. ansible/executor/action_write_locks.py +0 -44
  736. ansible/executor/discovery/python_target.py +0 -47
  737. ansible/executor/powershell/module_powershell_wrapper.ps1 +0 -86
  738. ansible/executor/powershell/module_script_wrapper.ps1 +0 -22
  739. ansible/module_utils/compat/importlib.py +0 -26
  740. ansible/module_utils/compat/selectors.py +0 -32
  741. ansible/module_utils/pycompat24.py +0 -73
  742. ansible/parsing/yaml/constructor.py +0 -178
  743. ansible/template/native_helpers.py +0 -251
  744. ansible/template/template.py +0 -43
  745. ansible/template/vars.py +0 -77
  746. ansible/utils/native_jinja.py +0 -11
  747. ansible/vars/fact_cache.py +0 -71
  748. ansible_core-2.18.7rc1.dist-info/RECORD +0 -992
  749. ansible_test/_util/controller/sanity/pylint/plugins/deprecated.py +0 -411
  750. {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/WHEEL +0 -0
  751. {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/entry_points.txt +0 -0
  752. {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/COPYING +0 -0
  753. {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/Apache-License.txt +0 -0
  754. {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/MIT-license.txt +0 -0
  755. {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/PSF-license.txt +0 -0
  756. {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/simplified_bsd.txt +0 -0
  757. {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,592 @@
1
+ # (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.com>
2
+ # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
3
+
4
+ from __future__ import annotations
5
+
6
+ import copy
7
+ import dataclasses
8
+ import enum
9
+ import textwrap
10
+ import typing as t
11
+ import collections.abc as c
12
+ import re
13
+
14
+ from collections import ChainMap
15
+
16
+ from ansible.errors import (
17
+ AnsibleError,
18
+ AnsibleValueOmittedError,
19
+ AnsibleUndefinedVariable,
20
+ AnsibleTemplateSyntaxError,
21
+ AnsibleBrokenConditionalError,
22
+ AnsibleTemplateTransformLimitError,
23
+ TemplateTrustCheckFailedError,
24
+ )
25
+
26
+ from ansible.module_utils._internal._datatag import AnsibleTaggedObject, NotTaggableError, AnsibleTagHelper
27
+ from ansible._internal._errors._handler import Skippable
28
+ from ansible._internal._datatag._tags import Origin, TrustedAsTemplate
29
+ from ansible.utils.display import Display
30
+ from ansible.utils.vars import validate_variable_name
31
+ from ansible.parsing.dataloader import DataLoader
32
+
33
+ from ._datatag import DeprecatedAccessAuditContext
34
+ from ._jinja_bits import (
35
+ AnsibleTemplate,
36
+ _TemplateCompileContext,
37
+ TemplateOverrides,
38
+ AnsibleEnvironment,
39
+ defer_template_error,
40
+ create_template_error,
41
+ is_possibly_template,
42
+ is_possibly_all_template,
43
+ AnsibleTemplateExpression,
44
+ _finalize_template_result,
45
+ FinalizeMode,
46
+ )
47
+ from ._jinja_common import _TemplateConfig, MarkerError, ExceptionMarker
48
+ from ._lazy_containers import _AnsibleLazyTemplateMixin
49
+ from ._marker_behaviors import MarkerBehavior, FAIL_ON_UNDEFINED
50
+ from ._transform import _type_transform_mapping
51
+ from ._utils import Omit, TemplateContext, IGNORE_SCALAR_VAR_TYPES, LazyOptions
52
+ from ...module_utils.datatag import native_type_name
53
+
54
+ _display = Display()
55
+
56
+
57
+ _shared_empty_unmask_type_names: frozenset[str] = frozenset()
58
+
59
+ TRANSFORM_CHAIN_LIMIT: int = 10
60
+ """Arbitrary limit for chained transforms to prevent cycles; an exception will be raised if exceeded."""
61
+
62
+
63
+ class TemplateMode(enum.Enum):
64
+ # DTFIX-FUTURE: this enum ideally wouldn't exist - revisit/rename before making public
65
+ DEFAULT = enum.auto()
66
+ STOP_ON_TEMPLATE = enum.auto()
67
+ STOP_ON_CONTAINER = enum.auto()
68
+ ALWAYS_FINALIZE = enum.auto()
69
+
70
+
71
+ @dataclasses.dataclass(kw_only=True, slots=True, frozen=True)
72
+ class TemplateOptions:
73
+ DEFAULT: t.ClassVar[t.Self]
74
+
75
+ value_for_omit: object = Omit
76
+ escape_backslashes: bool = True
77
+ preserve_trailing_newlines: bool = True
78
+ # DTFIX-FUTURE: these aren't really overrides anymore, rename the dataclass and this field
79
+ # also mention in docstring this has no effect unless used to template a string
80
+ overrides: TemplateOverrides = TemplateOverrides.DEFAULT
81
+
82
+
83
+ TemplateOptions.DEFAULT = TemplateOptions()
84
+
85
+
86
+ class TemplateEncountered(Exception):
87
+ pass
88
+
89
+
90
+ class TemplateEngine:
91
+ """
92
+ The main class for templating, with the main entry-point of template().
93
+ """
94
+
95
+ _sentinel = object()
96
+
97
+ def __init__(
98
+ self,
99
+ loader: DataLoader | None = None,
100
+ variables: dict[str, t.Any] | ChainMap[str, t.Any] | None = None,
101
+ variables_factory: t.Callable[[], dict[str, t.Any] | ChainMap[str, t.Any]] | None = None,
102
+ marker_behavior: MarkerBehavior | None = None,
103
+ ):
104
+ self._loader = loader
105
+ self._variables = variables
106
+ self._variables_factory = variables_factory
107
+ self._environment: AnsibleEnvironment | None = None
108
+
109
+ # inherit marker behavior from the active template context's templar unless otherwise specified
110
+ if not marker_behavior:
111
+ if template_ctx := TemplateContext.current(optional=True):
112
+ marker_behavior = template_ctx.templar.marker_behavior
113
+ else:
114
+ marker_behavior = FAIL_ON_UNDEFINED
115
+
116
+ self._marker_behavior = marker_behavior
117
+
118
+ def copy(self) -> t.Self:
119
+ new_engine = copy.copy(self)
120
+ new_engine._environment = None
121
+
122
+ return new_engine
123
+
124
+ def extend(self, marker_behavior: MarkerBehavior | None = None) -> t.Self:
125
+ new_templar = type(self)(
126
+ loader=self._loader,
127
+ variables=self._variables,
128
+ variables_factory=self._variables_factory,
129
+ marker_behavior=marker_behavior or self._marker_behavior,
130
+ )
131
+
132
+ if self._environment:
133
+ new_templar._environment = self._environment
134
+
135
+ return new_templar
136
+
137
+ @property
138
+ def marker_behavior(self) -> MarkerBehavior:
139
+ return self._marker_behavior
140
+
141
+ @property
142
+ def basedir(self) -> str:
143
+ """The basedir from DataLoader."""
144
+ return self._loader.get_basedir() if self._loader else '.'
145
+
146
+ @property
147
+ def environment(self) -> AnsibleEnvironment:
148
+ if not self._environment:
149
+ self._environment = AnsibleEnvironment(ansible_basedir=self.basedir)
150
+
151
+ return self._environment
152
+
153
+ def _create_overlay(self, template: str, overrides: TemplateOverrides) -> tuple[str, AnsibleEnvironment]:
154
+ try:
155
+ template, overrides = overrides._extract_template_overrides(template)
156
+ except Exception as ex:
157
+ raise AnsibleTemplateSyntaxError("Syntax error in template.", obj=template) from ex
158
+
159
+ env = self.environment
160
+
161
+ if overrides is not TemplateOverrides.DEFAULT and (overlay_kwargs := overrides.overlay_kwargs()):
162
+ env = t.cast(AnsibleEnvironment, env.overlay(**overlay_kwargs))
163
+
164
+ return template, env
165
+
166
+ @staticmethod
167
+ def _count_newlines_from_end(in_str):
168
+ """
169
+ Counts the number of newlines at the end of a string. This is used during
170
+ the jinja2 templating to ensure the count matches the input, since some newlines
171
+ may be thrown away during the templating.
172
+ """
173
+
174
+ i = len(in_str)
175
+ j = i - 1
176
+
177
+ try:
178
+ while in_str[j] == '\n':
179
+ j -= 1
180
+ except IndexError:
181
+ # Uncommon cases: zero length string and string containing only newlines
182
+ return i
183
+
184
+ return i - 1 - j
185
+
186
+ @property
187
+ def available_variables(self) -> dict[str, t.Any] | ChainMap[str, t.Any]:
188
+ """Available variables this instance will use when templating."""
189
+ # DTFIX3: ensure that we're always accessing this as a shallow container-level snapshot, and eliminate uses of anything
190
+ # that directly mutates this value. _new_context may resolve this for us?
191
+ if self._variables is None:
192
+ self._variables = self._variables_factory() if self._variables_factory else {}
193
+
194
+ return self._variables
195
+
196
+ @available_variables.setter
197
+ def available_variables(self, variables: dict[str, t.Any]) -> None:
198
+ self._variables = variables
199
+
200
+ def resolve_variable_expression(
201
+ self,
202
+ expression: str,
203
+ *,
204
+ local_variables: dict[str, t.Any] | None = None,
205
+ ) -> t.Any:
206
+ """
207
+ Resolve a potentially untrusted string variable expression consisting only of valid identifiers, integers, dots, and indexing containing these.
208
+ Optional local variables may be provided, which can only be referenced directly by the given expression.
209
+ Valid: x, x.y, x[y].z, x[1], 1, x[y.z]
210
+ Error: 'x', x['y'], q('env')
211
+ """
212
+ components = re.split(r'[.\[\]]', expression)
213
+
214
+ try:
215
+ for component in components:
216
+ if re.fullmatch('[0-9]*', component):
217
+ continue # allow empty strings and integers
218
+
219
+ validate_variable_name(component)
220
+ except Exception as ex:
221
+ raise AnsibleError(f'Invalid variable expression: {expression}', obj=expression) from ex
222
+
223
+ return self.evaluate_expression(TrustedAsTemplate().tag(expression), local_variables=local_variables)
224
+
225
+ @staticmethod
226
+ def variable_name_as_template(name: str) -> str:
227
+ """Return a trusted template string that will resolve the provided variable name. Raises an error if `name` is not a valid identifier."""
228
+ validate_variable_name(name)
229
+ return AnsibleTagHelper.tag('{{' + name + '}}', (AnsibleTagHelper.tags(name) | {TrustedAsTemplate()}))
230
+
231
+ def transform(self, variable: t.Any) -> t.Any:
232
+ """Recursively apply transformations to the given value and return the result."""
233
+ return self.template(variable, mode=TemplateMode.ALWAYS_FINALIZE, lazy_options=LazyOptions.SKIP_TEMPLATES_AND_ACCESS)
234
+
235
+ def template(
236
+ self,
237
+ variable: t.Any, # DTFIX-FUTURE: once we settle the new/old API boundaries, rename this (here and in other methods)
238
+ *,
239
+ options: TemplateOptions = TemplateOptions.DEFAULT,
240
+ mode: TemplateMode = TemplateMode.DEFAULT,
241
+ lazy_options: LazyOptions = LazyOptions.DEFAULT,
242
+ ) -> t.Any:
243
+ """Templates (possibly recursively) any given data as input."""
244
+ original_variable = variable
245
+
246
+ for _attempt in range(TRANSFORM_CHAIN_LIMIT):
247
+ if variable is None or (value_type := type(variable)) in IGNORE_SCALAR_VAR_TYPES:
248
+ return variable # quickly ignore supported scalar types which are not be templated
249
+
250
+ value_is_str = isinstance(variable, str)
251
+
252
+ if template_ctx := TemplateContext.current(optional=True):
253
+ stop_on_template = template_ctx.stop_on_template
254
+ else:
255
+ stop_on_template = False
256
+
257
+ if mode is TemplateMode.STOP_ON_TEMPLATE:
258
+ stop_on_template = True
259
+
260
+ with (
261
+ TemplateContext(template_value=variable, templar=self, options=options, stop_on_template=stop_on_template) as ctx,
262
+ DeprecatedAccessAuditContext.when(ctx.is_top_level),
263
+ ):
264
+ try:
265
+ if not value_is_str:
266
+ # transforms are currently limited to non-str types as an optimization
267
+ if (transform := _type_transform_mapping.get(value_type)) and value_type.__name__ not in lazy_options.unmask_type_names:
268
+ variable = transform(variable)
269
+ continue
270
+
271
+ template_result = _AnsibleLazyTemplateMixin._try_create(variable, lazy_options)
272
+ elif not lazy_options.template:
273
+ template_result = variable
274
+ elif not is_possibly_template(variable, options.overrides):
275
+ template_result = variable
276
+ elif not self._trust_check(variable, skip_handler=stop_on_template):
277
+ template_result = variable
278
+ elif stop_on_template:
279
+ raise TemplateEncountered()
280
+ else:
281
+ compiled_template = self._compile_template(variable, options)
282
+
283
+ template_result = compiled_template(self.available_variables)
284
+ template_result = self._post_render_mutation(variable, template_result, options)
285
+ except TemplateEncountered:
286
+ raise
287
+ except Exception as ex:
288
+ template_result = defer_template_error(ex, variable, is_expression=False)
289
+
290
+ if ctx.is_top_level or mode is TemplateMode.ALWAYS_FINALIZE:
291
+ template_result = self._finalize_top_level_template_result(
292
+ variable, options, template_result, stop_on_container=mode is TemplateMode.STOP_ON_CONTAINER
293
+ )
294
+
295
+ return template_result
296
+
297
+ raise AnsibleTemplateTransformLimitError(obj=original_variable)
298
+
299
+ @staticmethod
300
+ def _finalize_top_level_template_result(
301
+ variable: t.Any,
302
+ options: TemplateOptions,
303
+ template_result: t.Any,
304
+ is_expression: bool = False,
305
+ stop_on_container: bool = False,
306
+ ) -> t.Any:
307
+ """
308
+ This method must be called for expressions and top-level templates to recursively finalize the result.
309
+ This renders any embedded templates and triggers `Marker` and omit behaviors.
310
+ """
311
+ try:
312
+ if template_result is Omit:
313
+ # When the template result is Omit, raise an AnsibleValueOmittedError if value_for_omit is Omit, otherwise return value_for_omit.
314
+ # Other occurrences of Omit will simply drop out of containers during _finalize_template_result.
315
+ if options.value_for_omit is Omit:
316
+ raise AnsibleValueOmittedError()
317
+
318
+ return options.value_for_omit # trust that value_for_omit is an allowed type
319
+
320
+ if stop_on_container and type(template_result) in AnsibleTaggedObject._collection_types:
321
+ # Use of stop_on_container implies the caller will perform necessary checks on values,
322
+ # most likely by passing them back into the templating system.
323
+ try:
324
+ return template_result._non_lazy_copy()
325
+ except AttributeError:
326
+ return template_result # non-lazy containers are returned as-is
327
+
328
+ return _finalize_template_result(template_result, FinalizeMode.TOP_LEVEL)
329
+ except TemplateEncountered:
330
+ raise
331
+ except Exception as ex:
332
+ raise_from: BaseException
333
+
334
+ if isinstance(ex, MarkerError):
335
+ exception_to_raise = ex.source._as_exception()
336
+
337
+ # MarkerError is never suitable for use as the cause of another exception, it is merely a raiseable container for the source marker
338
+ # used for flow control (so its stack trace is rarely useful). However, if the source derives from a ExceptionMarker, its contained
339
+ # exception (previously raised) should be used as the cause. Other sources do not contain exceptions, so cannot provide a cause.
340
+ raise_from = exception_to_raise if isinstance(ex.source, ExceptionMarker) else None
341
+ else:
342
+ exception_to_raise = ex
343
+ raise_from = ex
344
+
345
+ exception_to_raise = create_template_error(exception_to_raise, variable, is_expression)
346
+
347
+ if exception_to_raise is ex:
348
+ raise # when the exception to raise is the active exception, just re-raise it
349
+
350
+ if exception_to_raise is raise_from:
351
+ raise_from = exception_to_raise.__cause__ # preserve the exception's cause, if any, otherwise no cause will be used
352
+
353
+ raise exception_to_raise from raise_from # always raise from something to avoid the currently active exception becoming __context__
354
+
355
+ def _compile_template(self, template: str, options: TemplateOptions) -> t.Callable[[c.Mapping[str, t.Any]], t.Any]:
356
+ # NOTE: Creating an overlay that lives only inside _compile_template means that overrides are not applied
357
+ # when templating nested variables, where Templar.environment is used, not the overlay. They are, however,
358
+ # applied to includes and imports.
359
+ try:
360
+ stripped_template, env = self._create_overlay(template, options.overrides)
361
+
362
+ with _TemplateCompileContext(escape_backslashes=options.escape_backslashes):
363
+ return t.cast(AnsibleTemplate, env.from_string(stripped_template))
364
+ except Exception as ex:
365
+ return self._defer_jinja_compile_error(ex, template, False)
366
+
367
+ def _compile_expression(self, expression: str, options: TemplateOptions) -> t.Callable[[c.Mapping[str, t.Any]], t.Any]:
368
+ """
369
+ Compile a Jinja expression, applying optional compile-time behavior via an environment overlay (if needed). The overlay is
370
+ necessary to avoid mutating settings on the Templar's shared environment, which could be visible to other code running concurrently.
371
+ In the specific case of escape_backslashes, the setting only applies to a top-level template at compile-time, not runtime, to
372
+ ensure that any nested template calls (e.g., include and import) do not inherit the (lack of) escaping behavior.
373
+ """
374
+ try:
375
+ with _TemplateCompileContext(escape_backslashes=options.escape_backslashes):
376
+ return AnsibleTemplateExpression(self.environment.compile_expression(expression, False))
377
+ except Exception as ex:
378
+ return self._defer_jinja_compile_error(ex, expression, True)
379
+
380
+ def _defer_jinja_compile_error(self, ex: Exception, variable: str, is_expression: bool) -> t.Callable[[c.Mapping[str, t.Any]], t.Any]:
381
+ deferred_error = defer_template_error(ex, variable, is_expression=is_expression)
382
+
383
+ def deferred_exception(_jinja_vars: c.Mapping[str, t.Any]) -> t.Any:
384
+ # a template/expression compile error always results in a single node representing the compile error
385
+ return self.marker_behavior.handle_marker(deferred_error)
386
+
387
+ return deferred_exception
388
+
389
+ def _post_render_mutation(self, template: str, result: t.Any, options: TemplateOptions) -> t.Any:
390
+ if options.preserve_trailing_newlines and isinstance(result, str):
391
+ # The low level calls above do not preserve the newline
392
+ # characters at the end of the input data, so we
393
+ # calculate the difference in newlines and append them
394
+ # to the resulting output for parity
395
+ #
396
+ # Using AnsibleEnvironment's keep_trailing_newline instead would
397
+ # result in change in behavior when trailing newlines
398
+ # would be kept also for included templates, for example:
399
+ # "Hello {% include 'world.txt' %}!" would render as
400
+ # "Hello world\n!\n" instead of "Hello world!\n".
401
+ data_newlines = self._count_newlines_from_end(template)
402
+ res_newlines = self._count_newlines_from_end(result)
403
+
404
+ if data_newlines > res_newlines:
405
+ newlines = options.overrides.newline_sequence * (data_newlines - res_newlines)
406
+ result = AnsibleTagHelper.tag_copy(result, result + newlines)
407
+
408
+ # If the input string template was source-tagged and the result is not, propagate the source tag to the new value.
409
+ # This provides further contextual information when a template-derived value/var causes an error.
410
+ if not Origin.is_tagged_on(result) and (origin := Origin.get_tag(template)):
411
+ try:
412
+ result = origin.tag(result)
413
+ except NotTaggableError:
414
+ pass # best effort- if we can't, oh well
415
+
416
+ return result
417
+
418
+ def is_template(self, data: t.Any, overrides: TemplateOverrides = TemplateOverrides.DEFAULT) -> bool:
419
+ """
420
+ Evaluate the input data to determine if it contains a template, even if that template is invalid. Containers will be recursively searched.
421
+ Objects subject to template-time transforms that do not yield a template are not considered templates by this method.
422
+ Gating a conditional call to `template` with this method is redundant and inefficient -- request templating unconditionally instead.
423
+ """
424
+ options = TemplateOptions(overrides=overrides) if overrides is not TemplateOverrides.DEFAULT else TemplateOptions.DEFAULT
425
+
426
+ try:
427
+ self.template(data, options=options, mode=TemplateMode.STOP_ON_TEMPLATE)
428
+ except TemplateEncountered:
429
+ return True
430
+ else:
431
+ return False
432
+
433
+ def resolve_to_container(self, variable: t.Any, options: TemplateOptions = TemplateOptions.DEFAULT) -> t.Any:
434
+ """
435
+ Recursively resolve scalar string template input, stopping at the first container encountered (if any).
436
+ Used for e.g., partial templating of task arguments, where the plugin needs to handle final resolution of some args internally.
437
+ """
438
+ return self.template(variable, options=options, mode=TemplateMode.STOP_ON_CONTAINER)
439
+
440
+ def evaluate_expression(
441
+ self,
442
+ expression: str,
443
+ *,
444
+ local_variables: dict[str, t.Any] | None = None,
445
+ escape_backslashes: bool = True,
446
+ _render_jinja_const_template: bool = False,
447
+ ) -> t.Any:
448
+ """
449
+ Evaluate a trusted string expression and return its result.
450
+ Optional local variables may be provided, which can only be referenced directly by the given expression.
451
+ """
452
+ if not isinstance(expression, str):
453
+ raise TypeError(f"Expressions must be {str!r}, got {type(expression)!r}.")
454
+
455
+ options = TemplateOptions(escape_backslashes=escape_backslashes, preserve_trailing_newlines=False)
456
+
457
+ with (
458
+ TemplateContext(template_value=expression, templar=self, options=options, _render_jinja_const_template=_render_jinja_const_template) as ctx,
459
+ DeprecatedAccessAuditContext.when(ctx.is_top_level),
460
+ ):
461
+ try:
462
+ if not TrustedAsTemplate.is_tagged_on(expression):
463
+ raise TemplateTrustCheckFailedError(obj=expression)
464
+
465
+ template_variables = ChainMap(local_variables, self.available_variables) if local_variables else self.available_variables
466
+ compiled_template = self._compile_expression(expression, options)
467
+
468
+ template_result = compiled_template(template_variables)
469
+ template_result = self._post_render_mutation(expression, template_result, options)
470
+ except Exception as ex:
471
+ template_result = defer_template_error(ex, expression, is_expression=True)
472
+
473
+ return self._finalize_top_level_template_result(expression, options, template_result, is_expression=True)
474
+
475
+ _BROKEN_CONDITIONAL_ALLOWED_FRAGMENT = 'Broken conditionals are currently allowed because the `ALLOW_BROKEN_CONDITIONALS` configuration option is enabled.'
476
+ _CONDITIONAL_AS_TEMPLATE_MSG = 'Conditionals should not be surrounded by templating delimiters such as {{ }} or {% %}.'
477
+
478
+ def _strip_conditional_handle_empty(self, conditional) -> t.Any:
479
+ """
480
+ Strips leading/trailing whitespace from the input expression.
481
+ If `ALLOW_BROKEN_CONDITIONALS` is enabled, None/empty is coerced to True (legacy behavior, deprecated).
482
+ Otherwise, None/empty results in a broken conditional error being raised.
483
+ """
484
+ if isinstance(conditional, str):
485
+ # Leading/trailing whitespace on conditional expressions is not a problem, except we can't tell if the expression is empty (which *is* a problem).
486
+ # Always strip conditional input strings. Neither conditional expressions nor all-template conditionals have legit reasons to preserve
487
+ # surrounding whitespace, and they complicate detection and processing of all-template fallback cases.
488
+ conditional = AnsibleTagHelper.tag_copy(conditional, conditional.strip())
489
+
490
+ if conditional in (None, ''):
491
+ # deprecated backward-compatible behavior; None/empty input conditionals are always True
492
+ if _TemplateConfig.allow_broken_conditionals:
493
+ _display.deprecated(
494
+ msg='Empty conditional expression was evaluated as True.',
495
+ help_text=self._BROKEN_CONDITIONAL_ALLOWED_FRAGMENT,
496
+ obj=conditional,
497
+ version='2.23',
498
+ )
499
+
500
+ return True
501
+
502
+ raise AnsibleBrokenConditionalError("Empty conditional expressions are not allowed.", obj=conditional)
503
+
504
+ return conditional
505
+
506
+ def _normalize_and_evaluate_conditional(self, conditional: str | bool) -> t.Any:
507
+ """Validate and normalize a conditional input value, resolving allowed embedded template cases and evaluating the resulting expression."""
508
+ conditional = self._strip_conditional_handle_empty(conditional)
509
+
510
+ # this must follow `_strip_conditional_handle_empty`, since None/empty are coerced to bool (deprecated)
511
+ if type(conditional) is bool: # pylint: disable=unidiomatic-typecheck
512
+ return conditional
513
+
514
+ try:
515
+ if not isinstance(conditional, str):
516
+ if _TemplateConfig.allow_broken_conditionals:
517
+ # because the input isn't a string, the result will never be a bool; the broken conditional warning in the caller will apply on the result
518
+ return self.template(conditional, mode=TemplateMode.ALWAYS_FINALIZE)
519
+
520
+ raise AnsibleBrokenConditionalError(message="Conditional expressions must be strings.", obj=conditional)
521
+
522
+ if is_possibly_all_template(conditional):
523
+ # Indirection of trusted expressions is always allowed. If the expression appears to be entirely wrapped in template delimiters,
524
+ # we must resolve it. e.g. `when: "{{ some_var_resolving_to_a_trusted_expression_string }}"`.
525
+ # Some invalid meta-templating corner cases may sneak through here (e.g., `when: '{{ "foo" }} == {{ "bar" }}'`); these will
526
+ # result in an untrusted expression error.
527
+ result = self.template(conditional, mode=TemplateMode.ALWAYS_FINALIZE)
528
+ result = self._strip_conditional_handle_empty(result)
529
+
530
+ if not isinstance(result, str):
531
+ _display.deprecated(msg=self._CONDITIONAL_AS_TEMPLATE_MSG, obj=conditional, version='2.23')
532
+
533
+ return result # not an expression
534
+
535
+ # The only allowed use of templates for conditionals is for indirect usage of an expression.
536
+ # Any other usage should simply be an expression, not an attempt at meta templating.
537
+ expression = result
538
+ else:
539
+ expression = conditional
540
+
541
+ # Disable escape_backslashes when processing conditionals, to maintain backwards compatibility.
542
+ # This is necessary because conditionals were previously evaluated using {% %}, which was *NOT* affected by escape_backslashes.
543
+ # Now that conditionals use expressions, they would be affected by escape_backslashes if it was not disabled.
544
+ return self.evaluate_expression(expression, escape_backslashes=False, _render_jinja_const_template=True)
545
+
546
+ except AnsibleUndefinedVariable as ex:
547
+ # DTFIX-FUTURE: we're only augmenting the message for context here; once we have proper contextual tracking, we can dump the re-raise
548
+ raise AnsibleUndefinedVariable("Error while evaluating conditional.", obj=conditional) from ex
549
+
550
+ def evaluate_conditional(self, conditional: str | bool) -> bool:
551
+ """
552
+ Evaluate a trusted string expression or boolean and return its boolean result. A non-boolean result will raise `AnsibleBrokenConditionalError`.
553
+ The ALLOW_BROKEN_CONDITIONALS configuration option can temporarily relax this requirement, allowing truthy conditionals to succeed.
554
+ """
555
+ result = self._normalize_and_evaluate_conditional(conditional)
556
+
557
+ if isinstance(result, bool):
558
+ return result
559
+
560
+ bool_result = bool(result)
561
+
562
+ msg = (
563
+ f'Conditional result was {textwrap.shorten(str(result), width=40)!r} of type {native_type_name(result)!r}, '
564
+ f'which evaluates to {bool_result}. Conditionals must have a boolean result.'
565
+ )
566
+
567
+ if _TemplateConfig.allow_broken_conditionals:
568
+ _display.deprecated(
569
+ msg=msg,
570
+ obj=conditional,
571
+ help_text=self._BROKEN_CONDITIONAL_ALLOWED_FRAGMENT,
572
+ version='2.23',
573
+ )
574
+
575
+ return bool_result
576
+
577
+ raise AnsibleBrokenConditionalError(msg, obj=conditional)
578
+
579
+ @staticmethod
580
+ def _trust_check(value: str, skip_handler: bool = False) -> bool:
581
+ """
582
+ Return True if the given value is trusted for templating, otherwise return False.
583
+ When the value is not trusted, a warning or error may be generated, depending on configuration.
584
+ """
585
+ if TrustedAsTemplate.is_tagged_on(value):
586
+ return True
587
+
588
+ if not skip_handler:
589
+ with Skippable, _TemplateConfig.untrusted_template_handler.handle(TemplateTrustCheckFailedError, skip_on_ignore=True):
590
+ raise TemplateTrustCheckFailedError(obj=value)
591
+
592
+ return False
@@ -0,0 +1,28 @@
1
+ from __future__ import annotations
2
+
3
+ from ansible.errors import AnsibleTemplatePluginError
4
+
5
+
6
+ class AnsibleTemplatePluginRuntimeError(AnsibleTemplatePluginError):
7
+ """The specified template plugin (lookup/filter/test) raised an exception during execution."""
8
+
9
+ def __init__(self, plugin_type: str, plugin_name: str) -> None:
10
+ super().__init__(f'The {plugin_type} plugin {plugin_name!r} failed.')
11
+
12
+
13
+ class AnsibleTemplatePluginLoadError(AnsibleTemplatePluginError):
14
+ """The specified template plugin (lookup/filter/test) failed to load."""
15
+
16
+ def __init__(self, plugin_type: str, plugin_name: str) -> None:
17
+ super().__init__(f'The {plugin_type} plugin {plugin_name!r} failed to load.')
18
+
19
+
20
+ class AnsibleTemplatePluginNotFoundError(AnsibleTemplatePluginError, KeyError):
21
+ """
22
+ The specified template plugin (lookup/filter/test) was not found.
23
+ This exception extends KeyError since Jinja filter/test resolution requires a KeyError to detect missing plugins.
24
+ Jinja compilation fails if a non-KeyError is raised for a missing filter/test, even if the plugin will not be invoked (inconsistent with stock Jinja).
25
+ """
26
+
27
+ def __init__(self, plugin_type: str, plugin_name: str) -> None:
28
+ super().__init__(f'The {plugin_type} plugin {plugin_name!r} was not found.')