ansible-core 2.18.5rc1__py3-none-any.whl → 2.19.0b1__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.
Files changed (709) hide show
  1. ansible/_internal/__init__.py +53 -0
  2. ansible/_internal/_ansiballz.py +265 -0
  3. ansible/_internal/_datatag/__init__.py +0 -0
  4. ansible/_internal/_datatag/_tags.py +130 -0
  5. ansible/_internal/_datatag/_utils.py +19 -0
  6. ansible/_internal/_datatag/_wrappers.py +33 -0
  7. ansible/_internal/_errors/__init__.py +0 -0
  8. ansible/_internal/_errors/_captured.py +128 -0
  9. ansible/_internal/_errors/_handler.py +91 -0
  10. ansible/_internal/_errors/_utils.py +310 -0
  11. ansible/_internal/_json/__init__.py +160 -0
  12. ansible/_internal/_json/_legacy_encoder.py +34 -0
  13. ansible/_internal/_json/_profiles/__init__.py +0 -0
  14. ansible/_internal/_json/_profiles/_cache_persistence.py +55 -0
  15. ansible/_internal/_json/_profiles/_inventory_legacy.py +40 -0
  16. ansible/_internal/_json/_profiles/_legacy.py +198 -0
  17. ansible/_internal/_locking.py +21 -0
  18. ansible/_internal/_plugins/__init__.py +0 -0
  19. ansible/_internal/_plugins/_cache.py +57 -0
  20. ansible/_internal/_task.py +78 -0
  21. ansible/_internal/_templating/__init__.py +10 -0
  22. ansible/_internal/_templating/_access.py +86 -0
  23. ansible/_internal/_templating/_chain_templar.py +63 -0
  24. ansible/_internal/_templating/_datatag.py +95 -0
  25. ansible/_internal/_templating/_engine.py +588 -0
  26. ansible/_internal/_templating/_errors.py +28 -0
  27. ansible/_internal/_templating/_jinja_bits.py +1066 -0
  28. ansible/_internal/_templating/_jinja_common.py +332 -0
  29. ansible/_internal/_templating/_jinja_patches.py +44 -0
  30. ansible/_internal/_templating/_jinja_plugins.py +351 -0
  31. ansible/_internal/_templating/_lazy_containers.py +633 -0
  32. ansible/_internal/_templating/_marker_behaviors.py +103 -0
  33. ansible/_internal/_templating/_transform.py +63 -0
  34. ansible/_internal/_templating/_utils.py +107 -0
  35. ansible/_internal/_wrapt.py +1052 -0
  36. ansible/_internal/_yaml/__init__.py +0 -0
  37. ansible/_internal/_yaml/_constructor.py +240 -0
  38. ansible/_internal/_yaml/_dumper.py +62 -0
  39. ansible/_internal/_yaml/_errors.py +166 -0
  40. ansible/_internal/_yaml/_loader.py +66 -0
  41. ansible/_internal/ansible_collections/ansible/_protomatter/README.md +11 -0
  42. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/action/debug.py +36 -0
  43. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/apply_trust.py +19 -0
  44. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/dump_object.py +18 -0
  45. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/finalize.py +16 -0
  46. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/origin.py +18 -0
  47. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/python_literal_eval.py +24 -0
  48. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/python_literal_eval.yml +33 -0
  49. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/tag_names.py +16 -0
  50. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/true_type.py +17 -0
  51. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/unmask.py +49 -0
  52. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/lookup/config.py +21 -0
  53. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/lookup/config.yml +2 -0
  54. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged.py +15 -0
  55. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged.yml +19 -0
  56. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged_with.py +18 -0
  57. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged_with.yml +19 -0
  58. ansible/cli/__init__.py +153 -89
  59. ansible/cli/_ssh_askpass.py +47 -0
  60. ansible/cli/adhoc.py +14 -7
  61. ansible/cli/arguments/option_helpers.py +154 -7
  62. ansible/cli/config.py +43 -68
  63. ansible/cli/console.py +10 -8
  64. ansible/cli/doc.py +48 -46
  65. ansible/cli/galaxy.py +27 -20
  66. ansible/cli/inventory.py +28 -26
  67. ansible/cli/playbook.py +4 -12
  68. ansible/cli/pull.py +51 -11
  69. ansible/cli/scripts/ansible_connection_cli_stub.py +7 -7
  70. ansible/cli/vault.py +12 -11
  71. ansible/compat/__init__.py +2 -2
  72. ansible/config/base.yml +165 -108
  73. ansible/config/manager.py +52 -49
  74. ansible/constants.py +3 -4
  75. ansible/errors/__init__.py +277 -235
  76. ansible/executor/interpreter_discovery.py +28 -149
  77. ansible/executor/module_common.py +426 -493
  78. ansible/executor/play_iterator.py +22 -27
  79. ansible/executor/playbook_executor.py +11 -11
  80. ansible/executor/powershell/async_watchdog.ps1 +97 -102
  81. ansible/executor/powershell/async_wrapper.ps1 +202 -151
  82. ansible/executor/powershell/become_wrapper.ps1 +89 -144
  83. ansible/executor/powershell/bootstrap_wrapper.ps1 +24 -9
  84. ansible/executor/powershell/coverage_wrapper.ps1 +82 -135
  85. ansible/executor/powershell/exec_wrapper.ps1 +462 -196
  86. ansible/executor/powershell/module_manifest.py +417 -265
  87. ansible/executor/powershell/module_wrapper.ps1 +169 -186
  88. ansible/executor/powershell/psrp_fetch_file.ps1 +41 -0
  89. ansible/executor/powershell/psrp_put_file.ps1 +122 -0
  90. ansible/executor/powershell/winrm_fetch_file.ps1 +46 -0
  91. ansible/executor/powershell/winrm_put_file.ps1 +36 -0
  92. ansible/executor/process/worker.py +136 -76
  93. ansible/executor/stats.py +5 -5
  94. ansible/executor/task_executor.py +237 -236
  95. ansible/executor/task_queue_manager.py +62 -38
  96. ansible/executor/task_result.py +21 -12
  97. ansible/galaxy/__init__.py +2 -2
  98. ansible/galaxy/api.py +22 -18
  99. ansible/galaxy/collection/__init__.py +1 -1
  100. ansible/galaxy/collection/concrete_artifact_manager.py +8 -11
  101. ansible/galaxy/dependency_resolution/dataclasses.py +14 -4
  102. ansible/galaxy/dependency_resolution/providers.py +1 -1
  103. ansible/galaxy/dependency_resolution/reporters.py +81 -0
  104. ansible/galaxy/role.py +4 -8
  105. ansible/galaxy/token.py +28 -21
  106. ansible/inventory/data.py +47 -57
  107. ansible/inventory/group.py +44 -72
  108. ansible/inventory/helpers.py +9 -0
  109. ansible/inventory/host.py +32 -54
  110. ansible/inventory/manager.py +77 -34
  111. ansible/keyword_desc.yml +1 -1
  112. ansible/module_utils/_internal/__init__.py +55 -0
  113. ansible/module_utils/_internal/_ambient_context.py +58 -0
  114. ansible/module_utils/_internal/_ansiballz.py +133 -0
  115. ansible/module_utils/_internal/_concurrent/_daemon_threading.py +1 -0
  116. ansible/module_utils/_internal/_dataclass_annotation_patch.py +64 -0
  117. ansible/module_utils/_internal/_dataclass_validation.py +217 -0
  118. ansible/module_utils/_internal/_datatag/__init__.py +928 -0
  119. ansible/module_utils/_internal/_datatag/_tags.py +38 -0
  120. ansible/module_utils/_internal/_debugging.py +31 -0
  121. ansible/module_utils/_internal/_errors.py +30 -0
  122. ansible/module_utils/_internal/_json/__init__.py +63 -0
  123. ansible/module_utils/_internal/_json/_legacy_encoder.py +26 -0
  124. ansible/module_utils/_internal/_json/_profiles/__init__.py +410 -0
  125. ansible/module_utils/_internal/_json/_profiles/_fallback_to_str.py +73 -0
  126. ansible/module_utils/_internal/_json/_profiles/_module_legacy_c2m.py +31 -0
  127. ansible/module_utils/_internal/_json/_profiles/_module_legacy_m2c.py +35 -0
  128. ansible/module_utils/_internal/_json/_profiles/_module_modern_c2m.py +35 -0
  129. ansible/module_utils/_internal/_json/_profiles/_module_modern_m2c.py +33 -0
  130. ansible/module_utils/_internal/_json/_profiles/_tagless.py +50 -0
  131. ansible/module_utils/_internal/_patches/__init__.py +66 -0
  132. ansible/module_utils/_internal/_patches/_dataclass_annotation_patch.py +55 -0
  133. ansible/module_utils/_internal/_patches/_socket_patch.py +34 -0
  134. ansible/module_utils/_internal/_patches/_sys_intern_patch.py +34 -0
  135. ansible/module_utils/_internal/_plugin_exec_context.py +49 -0
  136. ansible/module_utils/_internal/_testing.py +0 -0
  137. ansible/module_utils/_internal/_traceback.py +89 -0
  138. ansible/module_utils/ansible_release.py +2 -2
  139. ansible/module_utils/api.py +1 -2
  140. ansible/module_utils/basic.py +154 -120
  141. ansible/module_utils/common/_utils.py +24 -28
  142. ansible/module_utils/common/collections.py +1 -2
  143. ansible/module_utils/common/dict_transformations.py +2 -2
  144. ansible/module_utils/common/file.py +2 -2
  145. ansible/module_utils/common/json.py +90 -84
  146. ansible/module_utils/common/locale.py +2 -2
  147. ansible/module_utils/common/messages.py +108 -0
  148. ansible/module_utils/common/parameters.py +27 -24
  149. ansible/module_utils/common/process.py +2 -2
  150. ansible/module_utils/common/respawn.py +41 -19
  151. ansible/module_utils/common/sentinel.py +66 -0
  152. ansible/module_utils/common/sys_info.py +8 -8
  153. ansible/module_utils/common/text/converters.py +16 -37
  154. ansible/module_utils/common/validation.py +35 -24
  155. ansible/module_utils/common/warnings.py +86 -25
  156. ansible/module_utils/common/yaml.py +29 -3
  157. ansible/module_utils/compat/datetime.py +33 -21
  158. ansible/module_utils/compat/paramiko.py +21 -10
  159. ansible/module_utils/compat/typing.py +6 -5
  160. ansible/module_utils/connection.py +2 -2
  161. ansible/module_utils/csharp/Ansible.Basic.cs +14 -11
  162. ansible/module_utils/csharp/Ansible.Become.cs +1 -0
  163. ansible/module_utils/csharp/Ansible._Async.cs +517 -0
  164. ansible/module_utils/datatag.py +46 -0
  165. ansible/module_utils/distro/__init__.py +2 -2
  166. ansible/module_utils/facts/ansible_collector.py +4 -5
  167. ansible/module_utils/facts/collector.py +13 -14
  168. ansible/module_utils/facts/compat.py +4 -4
  169. ansible/module_utils/facts/default_collectors.py +1 -1
  170. ansible/module_utils/facts/hardware/aix.py +34 -0
  171. ansible/module_utils/facts/hardware/base.py +1 -1
  172. ansible/module_utils/facts/hardware/darwin.py +1 -3
  173. ansible/module_utils/facts/hardware/freebsd.py +2 -2
  174. ansible/module_utils/facts/hardware/linux.py +4 -4
  175. ansible/module_utils/facts/namespace.py +1 -1
  176. ansible/module_utils/facts/network/base.py +1 -1
  177. ansible/module_utils/facts/network/fc_wwn.py +1 -2
  178. ansible/module_utils/facts/network/iscsi.py +1 -2
  179. ansible/module_utils/facts/network/nvme.py +1 -2
  180. ansible/module_utils/facts/other/facter.py +1 -2
  181. ansible/module_utils/facts/other/ohai.py +2 -3
  182. ansible/module_utils/facts/system/apparmor.py +1 -2
  183. ansible/module_utils/facts/system/caps.py +1 -1
  184. ansible/module_utils/facts/system/chroot.py +1 -2
  185. ansible/module_utils/facts/system/cmdline.py +1 -2
  186. ansible/module_utils/facts/system/date_time.py +5 -3
  187. ansible/module_utils/facts/system/distribution.py +9 -8
  188. ansible/module_utils/facts/system/dns.py +1 -1
  189. ansible/module_utils/facts/system/env.py +1 -2
  190. ansible/module_utils/facts/system/fips.py +7 -20
  191. ansible/module_utils/facts/system/loadavg.py +1 -2
  192. ansible/module_utils/facts/system/local.py +1 -2
  193. ansible/module_utils/facts/system/lsb.py +1 -2
  194. ansible/module_utils/facts/system/pkg_mgr.py +1 -2
  195. ansible/module_utils/facts/system/platform.py +1 -2
  196. ansible/module_utils/facts/system/python.py +1 -2
  197. ansible/module_utils/facts/system/selinux.py +1 -1
  198. ansible/module_utils/facts/system/service_mgr.py +1 -2
  199. ansible/module_utils/facts/system/ssh_pub_keys.py +1 -1
  200. ansible/module_utils/facts/system/systemd.py +1 -1
  201. ansible/module_utils/facts/system/user.py +1 -2
  202. ansible/module_utils/facts/utils.py +3 -3
  203. ansible/module_utils/facts/virtual/base.py +1 -1
  204. ansible/module_utils/facts/virtual/sunos.py +3 -15
  205. ansible/module_utils/facts/virtual/sysctl.py +3 -16
  206. ansible/module_utils/json_utils.py +2 -2
  207. ansible/module_utils/parsing/convert_bool.py +1 -1
  208. ansible/module_utils/service.py +18 -21
  209. ansible/module_utils/splitter.py +7 -7
  210. ansible/module_utils/testing.py +31 -0
  211. ansible/module_utils/urls.py +60 -31
  212. ansible/modules/add_host.py +4 -4
  213. ansible/modules/apt.py +60 -46
  214. ansible/modules/apt_key.py +19 -12
  215. ansible/modules/apt_repository.py +19 -16
  216. ansible/modules/assemble.py +6 -6
  217. ansible/modules/assert.py +4 -4
  218. ansible/modules/async_status.py +10 -12
  219. ansible/modules/async_wrapper.py +8 -3
  220. ansible/modules/blockinfile.py +6 -7
  221. ansible/modules/command.py +10 -17
  222. ansible/modules/copy.py +57 -144
  223. ansible/modules/cron.py +20 -15
  224. ansible/modules/deb822_repository.py +8 -9
  225. ansible/modules/debconf.py +5 -5
  226. ansible/modules/debug.py +4 -4
  227. ansible/modules/dnf.py +8 -8
  228. ansible/modules/dnf5.py +39 -13
  229. ansible/modules/dpkg_selections.py +4 -4
  230. ansible/modules/expect.py +8 -10
  231. ansible/modules/fail.py +4 -4
  232. ansible/modules/fetch.py +4 -4
  233. ansible/modules/file.py +174 -133
  234. ansible/modules/find.py +19 -17
  235. ansible/modules/gather_facts.py +3 -3
  236. ansible/modules/get_url.py +59 -53
  237. ansible/modules/getent.py +7 -9
  238. ansible/modules/git.py +28 -25
  239. ansible/modules/group.py +6 -6
  240. ansible/modules/group_by.py +4 -4
  241. ansible/modules/hostname.py +13 -29
  242. ansible/modules/import_playbook.py +6 -6
  243. ansible/modules/import_role.py +6 -6
  244. ansible/modules/import_tasks.py +6 -6
  245. ansible/modules/include_role.py +6 -6
  246. ansible/modules/include_tasks.py +6 -6
  247. ansible/modules/include_vars.py +6 -6
  248. ansible/modules/iptables.py +86 -73
  249. ansible/modules/known_hosts.py +10 -10
  250. ansible/modules/lineinfile.py +5 -5
  251. ansible/modules/meta.py +4 -4
  252. ansible/modules/mount_facts.py +2 -2
  253. ansible/modules/package.py +4 -4
  254. ansible/modules/package_facts.py +22 -10
  255. ansible/modules/pause.py +6 -6
  256. ansible/modules/ping.py +6 -6
  257. ansible/modules/pip.py +10 -11
  258. ansible/modules/raw.py +4 -4
  259. ansible/modules/reboot.py +6 -6
  260. ansible/modules/replace.py +9 -13
  261. ansible/modules/rpm_key.py +7 -8
  262. ansible/modules/script.py +4 -4
  263. ansible/modules/service.py +7 -8
  264. ansible/modules/service_facts.py +87 -10
  265. ansible/modules/set_fact.py +5 -5
  266. ansible/modules/set_stats.py +4 -4
  267. ansible/modules/setup.py +2 -2
  268. ansible/modules/shell.py +6 -6
  269. ansible/modules/slurp.py +6 -6
  270. ansible/modules/stat.py +9 -23
  271. ansible/modules/subversion.py +15 -15
  272. ansible/modules/systemd.py +6 -6
  273. ansible/modules/systemd_service.py +6 -6
  274. ansible/modules/sysvinit.py +6 -6
  275. ansible/modules/tempfile.py +5 -6
  276. ansible/modules/template.py +6 -6
  277. ansible/modules/unarchive.py +32 -11
  278. ansible/modules/uri.py +33 -26
  279. ansible/modules/user.py +53 -34
  280. ansible/modules/validate_argument_spec.py +10 -7
  281. ansible/modules/wait_for.py +32 -27
  282. ansible/modules/wait_for_connection.py +6 -6
  283. ansible/modules/yum_repository.py +6 -6
  284. ansible/parsing/ajson.py +14 -32
  285. ansible/parsing/dataloader.py +99 -54
  286. ansible/parsing/mod_args.py +28 -44
  287. ansible/parsing/plugin_docs.py +21 -86
  288. ansible/parsing/quoting.py +1 -1
  289. ansible/parsing/splitter.py +27 -12
  290. ansible/parsing/utils/addresses.py +24 -24
  291. ansible/parsing/utils/yaml.py +32 -61
  292. ansible/parsing/vault/__init__.py +319 -87
  293. ansible/parsing/yaml/__init__.py +0 -18
  294. ansible/parsing/yaml/dumper.py +6 -120
  295. ansible/parsing/yaml/loader.py +6 -39
  296. ansible/parsing/yaml/objects.py +36 -339
  297. ansible/playbook/__init__.py +1 -1
  298. ansible/playbook/attribute.py +8 -3
  299. ansible/playbook/base.py +182 -132
  300. ansible/playbook/block.py +26 -24
  301. ansible/playbook/collectionsearch.py +1 -15
  302. ansible/playbook/conditional.py +3 -77
  303. ansible/playbook/handler.py +8 -2
  304. ansible/playbook/helpers.py +41 -53
  305. ansible/playbook/included_file.py +6 -15
  306. ansible/playbook/loop_control.py +2 -2
  307. ansible/playbook/play.py +85 -44
  308. ansible/playbook/play_context.py +12 -17
  309. ansible/playbook/playbook_include.py +14 -15
  310. ansible/playbook/role/__init__.py +24 -26
  311. ansible/playbook/role/definition.py +15 -17
  312. ansible/playbook/role/include.py +2 -4
  313. ansible/playbook/role/metadata.py +10 -11
  314. ansible/playbook/role_include.py +3 -3
  315. ansible/playbook/taggable.py +13 -8
  316. ansible/playbook/task.py +188 -118
  317. ansible/playbook/task_include.py +5 -5
  318. ansible/plugins/__init__.py +68 -21
  319. ansible/plugins/action/__init__.py +209 -176
  320. ansible/plugins/action/add_host.py +1 -1
  321. ansible/plugins/action/assemble.py +1 -1
  322. ansible/plugins/action/assert.py +54 -66
  323. ansible/plugins/action/copy.py +7 -11
  324. ansible/plugins/action/debug.py +37 -31
  325. ansible/plugins/action/dnf.py +3 -4
  326. ansible/plugins/action/fail.py +1 -1
  327. ansible/plugins/action/fetch.py +4 -5
  328. ansible/plugins/action/gather_facts.py +7 -6
  329. ansible/plugins/action/group_by.py +1 -1
  330. ansible/plugins/action/include_vars.py +10 -11
  331. ansible/plugins/action/package.py +3 -6
  332. ansible/plugins/action/pause.py +2 -2
  333. ansible/plugins/action/script.py +15 -8
  334. ansible/plugins/action/service.py +6 -11
  335. ansible/plugins/action/set_fact.py +3 -12
  336. ansible/plugins/action/set_stats.py +3 -8
  337. ansible/plugins/action/template.py +35 -59
  338. ansible/plugins/action/unarchive.py +1 -1
  339. ansible/plugins/action/validate_argument_spec.py +5 -5
  340. ansible/plugins/action/wait_for_connection.py +1 -1
  341. ansible/plugins/become/__init__.py +31 -8
  342. ansible/plugins/become/runas.py +71 -0
  343. ansible/plugins/become/su.py +13 -8
  344. ansible/plugins/become/sudo.py +19 -0
  345. ansible/plugins/cache/__init__.py +35 -44
  346. ansible/plugins/cache/base.py +8 -0
  347. ansible/plugins/cache/jsonfile.py +10 -16
  348. ansible/plugins/cache/memory.py +6 -12
  349. ansible/plugins/callback/__init__.py +141 -123
  350. ansible/plugins/callback/default.py +30 -23
  351. ansible/plugins/callback/junit.py +28 -24
  352. ansible/plugins/callback/minimal.py +17 -14
  353. ansible/plugins/callback/oneline.py +13 -7
  354. ansible/plugins/callback/tree.py +10 -6
  355. ansible/plugins/connection/__init__.py +47 -34
  356. ansible/plugins/connection/local.py +150 -54
  357. ansible/plugins/connection/paramiko_ssh.py +21 -18
  358. ansible/plugins/connection/psrp.py +76 -165
  359. ansible/plugins/connection/ssh.py +301 -78
  360. ansible/plugins/connection/winrm.py +58 -140
  361. ansible/plugins/doc_fragments/action_common_attributes.py +14 -14
  362. ansible/plugins/doc_fragments/action_core.py +6 -6
  363. ansible/plugins/doc_fragments/backup.py +2 -2
  364. ansible/plugins/doc_fragments/checksum_common.py +27 -0
  365. ansible/plugins/doc_fragments/constructed.py +6 -2
  366. ansible/plugins/doc_fragments/decrypt.py +2 -2
  367. ansible/plugins/doc_fragments/default_callback.py +2 -2
  368. ansible/plugins/doc_fragments/files.py +2 -2
  369. ansible/plugins/doc_fragments/inventory_cache.py +2 -2
  370. ansible/plugins/doc_fragments/result_format_callback.py +2 -2
  371. ansible/plugins/doc_fragments/return_common.py +2 -2
  372. ansible/plugins/doc_fragments/template_common.py +4 -4
  373. ansible/plugins/doc_fragments/url.py +17 -1
  374. ansible/plugins/doc_fragments/url_windows.py +2 -2
  375. ansible/plugins/doc_fragments/validate.py +2 -2
  376. ansible/plugins/doc_fragments/vars_plugin_staging.py +2 -2
  377. ansible/plugins/filter/__init__.py +6 -2
  378. ansible/plugins/filter/b64decode.yml +22 -0
  379. ansible/plugins/filter/b64encode.yml +22 -0
  380. ansible/plugins/filter/bool.yml +11 -4
  381. ansible/plugins/filter/core.py +218 -108
  382. ansible/plugins/filter/encryption.py +32 -32
  383. ansible/plugins/filter/flatten.yml +3 -2
  384. ansible/plugins/filter/human_to_bytes.yml +1 -1
  385. ansible/plugins/filter/mathstuff.py +30 -37
  386. ansible/plugins/filter/password_hash.yml +8 -0
  387. ansible/plugins/filter/regex_search.yml +1 -4
  388. ansible/plugins/filter/split.yml +1 -1
  389. ansible/plugins/filter/to_nice_yaml.yml +0 -4
  390. ansible/plugins/filter/to_yaml.yml +0 -4
  391. ansible/plugins/filter/unvault.yml +1 -1
  392. ansible/plugins/filter/urls.py +1 -1
  393. ansible/plugins/filter/urlsplit.py +8 -9
  394. ansible/plugins/filter/vault.yml +14 -9
  395. ansible/plugins/filter/win_basename.yml +6 -1
  396. ansible/plugins/filter/win_dirname.yml +5 -0
  397. ansible/plugins/inventory/__init__.py +97 -77
  398. ansible/plugins/inventory/advanced_host_list.py +7 -5
  399. ansible/plugins/inventory/auto.py +11 -4
  400. ansible/plugins/inventory/constructed.py +21 -24
  401. ansible/plugins/inventory/generator.py +16 -11
  402. ansible/plugins/inventory/host_list.py +7 -5
  403. ansible/plugins/inventory/ini.py +78 -44
  404. ansible/plugins/inventory/script.py +189 -119
  405. ansible/plugins/inventory/toml.py +16 -126
  406. ansible/plugins/inventory/yaml.py +10 -8
  407. ansible/plugins/list.py +3 -3
  408. ansible/plugins/loader.py +197 -82
  409. ansible/plugins/lookup/__init__.py +21 -4
  410. ansible/plugins/lookup/config.py +21 -35
  411. ansible/plugins/lookup/csvfile.py +3 -2
  412. ansible/plugins/lookup/dict.py +1 -6
  413. ansible/plugins/lookup/env.py +12 -9
  414. ansible/plugins/lookup/file.py +5 -8
  415. ansible/plugins/lookup/first_found.py +86 -55
  416. ansible/plugins/lookup/indexed_items.py +1 -10
  417. ansible/plugins/lookup/ini.py +14 -13
  418. ansible/plugins/lookup/items.py +1 -1
  419. ansible/plugins/lookup/lines.py +8 -1
  420. ansible/plugins/lookup/list.py +1 -1
  421. ansible/plugins/lookup/nested.py +2 -18
  422. ansible/plugins/lookup/password.py +5 -5
  423. ansible/plugins/lookup/pipe.py +5 -7
  424. ansible/plugins/lookup/sequence.py +18 -8
  425. ansible/plugins/lookup/subelements.py +1 -4
  426. ansible/plugins/lookup/template.py +42 -36
  427. ansible/plugins/lookup/together.py +0 -12
  428. ansible/plugins/lookup/unvault.py +1 -5
  429. ansible/plugins/lookup/url.py +2 -8
  430. ansible/plugins/lookup/vars.py +16 -24
  431. ansible/plugins/shell/__init__.py +2 -2
  432. ansible/plugins/shell/cmd.py +2 -2
  433. ansible/plugins/shell/powershell.py +39 -22
  434. ansible/plugins/shell/sh.py +3 -2
  435. ansible/plugins/strategy/__init__.py +94 -113
  436. ansible/plugins/strategy/debug.py +2 -2
  437. ansible/plugins/strategy/free.py +13 -28
  438. ansible/plugins/strategy/host_pinned.py +2 -2
  439. ansible/plugins/strategy/linear.py +31 -33
  440. ansible/plugins/terminal/__init__.py +4 -4
  441. ansible/plugins/test/__init__.py +7 -2
  442. ansible/plugins/test/core.py +54 -20
  443. ansible/plugins/test/files.py +1 -1
  444. ansible/plugins/test/mathstuff.py +3 -3
  445. ansible/plugins/test/uri.py +3 -3
  446. ansible/plugins/vars/host_group_vars.py +7 -14
  447. ansible/release.py +2 -2
  448. ansible/template/__init__.py +368 -944
  449. ansible/utils/__init__.py +0 -18
  450. ansible/utils/_ssh_agent.py +657 -0
  451. ansible/utils/collection_loader/__init__.py +52 -5
  452. ansible/utils/collection_loader/_collection_config.py +5 -6
  453. ansible/utils/collection_loader/_collection_finder.py +79 -93
  454. ansible/utils/collection_loader/_collection_meta.py +13 -8
  455. ansible/utils/display.py +428 -58
  456. ansible/utils/encrypt.py +27 -19
  457. ansible/utils/fqcn.py +2 -2
  458. ansible/utils/hashing.py +2 -2
  459. ansible/utils/helpers.py +2 -2
  460. ansible/utils/listify.py +8 -8
  461. ansible/utils/lock.py +2 -2
  462. ansible/utils/path.py +4 -4
  463. ansible/utils/plugin_docs.py +14 -13
  464. ansible/utils/sentinel.py +4 -62
  465. ansible/utils/singleton.py +2 -0
  466. ansible/utils/ssh_functions.py +1 -1
  467. ansible/utils/unsafe_proxy.py +23 -332
  468. ansible/utils/vars.py +28 -8
  469. ansible/utils/version.py +2 -2
  470. ansible/vars/clean.py +4 -4
  471. ansible/vars/hostvars.py +60 -90
  472. ansible/vars/manager.py +205 -264
  473. ansible/vars/reserved.py +8 -9
  474. ansible_core-2.19.0b1.dist-info/BSD-3-Clause.txt +28 -0
  475. {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b1.dist-info}/METADATA +5 -4
  476. ansible_core-2.19.0b1.dist-info/RECORD +1070 -0
  477. {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b1.dist-info}/WHEEL +1 -1
  478. ansible_test/_data/completion/docker.txt +7 -7
  479. ansible_test/_data/completion/remote.txt +6 -6
  480. ansible_test/_data/completion/windows.txt +1 -0
  481. ansible_test/_data/requirements/ansible.txt +2 -2
  482. ansible_test/_data/requirements/sanity.ansible-doc.txt +3 -3
  483. ansible_test/_data/requirements/sanity.changelog.txt +1 -1
  484. ansible_test/_data/requirements/sanity.import.plugin.txt +2 -2
  485. ansible_test/_data/requirements/sanity.pylint.txt +4 -4
  486. ansible_test/_data/requirements/sanity.validate-modules.txt +2 -2
  487. ansible_test/_data/requirements/sanity.yamllint.txt +1 -1
  488. ansible_test/_data/requirements/units.txt +1 -0
  489. ansible_test/_internal/__init__.py +1 -0
  490. ansible_test/_internal/ansible_util.py +2 -0
  491. ansible_test/_internal/become.py +1 -0
  492. ansible_test/_internal/bootstrap.py +1 -0
  493. ansible_test/_internal/cache.py +1 -0
  494. ansible_test/_internal/cgroup.py +1 -0
  495. ansible_test/_internal/ci/__init__.py +1 -0
  496. ansible_test/_internal/ci/azp.py +1 -0
  497. ansible_test/_internal/ci/local.py +1 -0
  498. ansible_test/_internal/classification/__init__.py +1 -0
  499. ansible_test/_internal/classification/common.py +1 -0
  500. ansible_test/_internal/classification/csharp.py +1 -0
  501. ansible_test/_internal/classification/powershell.py +1 -0
  502. ansible_test/_internal/classification/python.py +1 -0
  503. ansible_test/_internal/cli/__init__.py +1 -0
  504. ansible_test/_internal/cli/actions.py +1 -0
  505. ansible_test/_internal/cli/argparsing/__init__.py +1 -0
  506. ansible_test/_internal/cli/argparsing/actions.py +1 -0
  507. ansible_test/_internal/cli/argparsing/argcompletion.py +1 -0
  508. ansible_test/_internal/cli/argparsing/parsers.py +1 -0
  509. ansible_test/_internal/cli/commands/__init__.py +11 -0
  510. ansible_test/_internal/cli/commands/coverage/__init__.py +1 -0
  511. ansible_test/_internal/cli/commands/coverage/analyze/__init__.py +1 -0
  512. ansible_test/_internal/cli/commands/coverage/analyze/targets/__init__.py +1 -0
  513. ansible_test/_internal/cli/commands/coverage/analyze/targets/combine.py +1 -0
  514. ansible_test/_internal/cli/commands/coverage/analyze/targets/expand.py +1 -0
  515. ansible_test/_internal/cli/commands/coverage/analyze/targets/filter.py +1 -0
  516. ansible_test/_internal/cli/commands/coverage/analyze/targets/generate.py +1 -0
  517. ansible_test/_internal/cli/commands/coverage/analyze/targets/missing.py +1 -0
  518. ansible_test/_internal/cli/commands/coverage/combine.py +1 -0
  519. ansible_test/_internal/cli/commands/coverage/erase.py +1 -0
  520. ansible_test/_internal/cli/commands/coverage/html.py +1 -0
  521. ansible_test/_internal/cli/commands/coverage/report.py +1 -0
  522. ansible_test/_internal/cli/commands/coverage/xml.py +1 -0
  523. ansible_test/_internal/cli/commands/env.py +1 -0
  524. ansible_test/_internal/cli/commands/integration/__init__.py +1 -0
  525. ansible_test/_internal/cli/commands/integration/network.py +1 -0
  526. ansible_test/_internal/cli/commands/integration/posix.py +1 -0
  527. ansible_test/_internal/cli/commands/integration/windows.py +1 -0
  528. ansible_test/_internal/cli/commands/sanity.py +9 -0
  529. ansible_test/_internal/cli/commands/shell.py +1 -0
  530. ansible_test/_internal/cli/commands/units.py +1 -0
  531. ansible_test/_internal/cli/compat.py +1 -0
  532. ansible_test/_internal/cli/completers.py +1 -0
  533. ansible_test/_internal/cli/converters.py +1 -0
  534. ansible_test/_internal/cli/environments.py +1 -0
  535. ansible_test/_internal/cli/epilog.py +1 -0
  536. ansible_test/_internal/cli/parsers/__init__.py +1 -0
  537. ansible_test/_internal/cli/parsers/base_argument_parsers.py +1 -0
  538. ansible_test/_internal/cli/parsers/helpers.py +1 -0
  539. ansible_test/_internal/cli/parsers/host_config_parsers.py +1 -0
  540. ansible_test/_internal/cli/parsers/key_value_parsers.py +1 -0
  541. ansible_test/_internal/cli/parsers/value_parsers.py +1 -0
  542. ansible_test/_internal/commands/__init__.py +1 -0
  543. ansible_test/_internal/commands/coverage/__init__.py +2 -1
  544. ansible_test/_internal/commands/coverage/analyze/__init__.py +1 -0
  545. ansible_test/_internal/commands/coverage/analyze/targets/__init__.py +1 -0
  546. ansible_test/_internal/commands/coverage/analyze/targets/combine.py +1 -0
  547. ansible_test/_internal/commands/coverage/analyze/targets/expand.py +1 -0
  548. ansible_test/_internal/commands/coverage/analyze/targets/filter.py +1 -0
  549. ansible_test/_internal/commands/coverage/analyze/targets/generate.py +1 -0
  550. ansible_test/_internal/commands/coverage/analyze/targets/missing.py +1 -0
  551. ansible_test/_internal/commands/coverage/combine.py +2 -1
  552. ansible_test/_internal/commands/coverage/erase.py +1 -0
  553. ansible_test/_internal/commands/coverage/html.py +1 -0
  554. ansible_test/_internal/commands/coverage/report.py +1 -0
  555. ansible_test/_internal/commands/coverage/xml.py +1 -0
  556. ansible_test/_internal/commands/env/__init__.py +2 -0
  557. ansible_test/_internal/commands/integration/__init__.py +4 -0
  558. ansible_test/_internal/commands/integration/cloud/__init__.py +1 -0
  559. ansible_test/_internal/commands/integration/cloud/acme.py +2 -1
  560. ansible_test/_internal/commands/integration/cloud/aws.py +1 -0
  561. ansible_test/_internal/commands/integration/cloud/azure.py +1 -0
  562. ansible_test/_internal/commands/integration/cloud/cs.py +1 -0
  563. ansible_test/_internal/commands/integration/cloud/digitalocean.py +1 -0
  564. ansible_test/_internal/commands/integration/cloud/galaxy.py +3 -2
  565. ansible_test/_internal/commands/integration/cloud/hcloud.py +1 -0
  566. ansible_test/_internal/commands/integration/cloud/httptester.py +2 -1
  567. ansible_test/_internal/commands/integration/cloud/nios.py +2 -1
  568. ansible_test/_internal/commands/integration/cloud/opennebula.py +1 -0
  569. ansible_test/_internal/commands/integration/cloud/openshift.py +1 -0
  570. ansible_test/_internal/commands/integration/cloud/scaleway.py +1 -0
  571. ansible_test/_internal/commands/integration/cloud/vcenter.py +1 -0
  572. ansible_test/_internal/commands/integration/cloud/vultr.py +1 -0
  573. ansible_test/_internal/commands/integration/coverage.py +1 -0
  574. ansible_test/_internal/commands/integration/filters.py +1 -0
  575. ansible_test/_internal/commands/integration/network.py +1 -0
  576. ansible_test/_internal/commands/integration/posix.py +1 -0
  577. ansible_test/_internal/commands/integration/windows.py +1 -0
  578. ansible_test/_internal/commands/sanity/__init__.py +16 -1
  579. ansible_test/_internal/commands/sanity/ansible_doc.py +1 -0
  580. ansible_test/_internal/commands/sanity/bin_symlinks.py +1 -0
  581. ansible_test/_internal/commands/sanity/compile.py +1 -0
  582. ansible_test/_internal/commands/sanity/ignores.py +1 -0
  583. ansible_test/_internal/commands/sanity/import.py +1 -0
  584. ansible_test/_internal/commands/sanity/integration_aliases.py +1 -0
  585. ansible_test/_internal/commands/sanity/pep8.py +1 -0
  586. ansible_test/_internal/commands/sanity/pslint.py +1 -0
  587. ansible_test/_internal/commands/sanity/pylint.py +24 -26
  588. ansible_test/_internal/commands/sanity/shellcheck.py +1 -0
  589. ansible_test/_internal/commands/sanity/validate_modules.py +1 -0
  590. ansible_test/_internal/commands/sanity/yamllint.py +1 -0
  591. ansible_test/_internal/commands/shell/__init__.py +1 -0
  592. ansible_test/_internal/commands/units/__init__.py +1 -0
  593. ansible_test/_internal/compat/__init__.py +1 -0
  594. ansible_test/_internal/compat/packaging.py +1 -0
  595. ansible_test/_internal/compat/yaml.py +1 -0
  596. ansible_test/_internal/completion.py +1 -0
  597. ansible_test/_internal/config.py +2 -0
  598. ansible_test/_internal/connections.py +1 -0
  599. ansible_test/_internal/constants.py +1 -0
  600. ansible_test/_internal/containers.py +1 -0
  601. ansible_test/_internal/content_config.py +1 -0
  602. ansible_test/_internal/core_ci.py +1 -0
  603. ansible_test/_internal/coverage_util.py +11 -10
  604. ansible_test/_internal/data.py +1 -0
  605. ansible_test/_internal/delegation.py +1 -0
  606. ansible_test/_internal/dev/__init__.py +1 -0
  607. ansible_test/_internal/dev/container_probe.py +1 -0
  608. ansible_test/_internal/diff.py +3 -2
  609. ansible_test/_internal/docker_util.py +2 -1
  610. ansible_test/_internal/encoding.py +1 -0
  611. ansible_test/_internal/executor.py +1 -0
  612. ansible_test/_internal/git.py +1 -0
  613. ansible_test/_internal/host_configs.py +1 -0
  614. ansible_test/_internal/host_profiles.py +1 -0
  615. ansible_test/_internal/http.py +1 -0
  616. ansible_test/_internal/init.py +1 -0
  617. ansible_test/_internal/inventory.py +35 -3
  618. ansible_test/_internal/io.py +1 -0
  619. ansible_test/_internal/metadata.py +1 -0
  620. ansible_test/_internal/payload.py +1 -0
  621. ansible_test/_internal/provider/__init__.py +1 -0
  622. ansible_test/_internal/provider/layout/__init__.py +1 -0
  623. ansible_test/_internal/provider/layout/ansible.py +1 -0
  624. ansible_test/_internal/provider/layout/collection.py +1 -0
  625. ansible_test/_internal/provider/layout/unsupported.py +1 -0
  626. ansible_test/_internal/provider/source/__init__.py +1 -0
  627. ansible_test/_internal/provider/source/git.py +1 -0
  628. ansible_test/_internal/provider/source/installed.py +1 -0
  629. ansible_test/_internal/provider/source/unsupported.py +1 -0
  630. ansible_test/_internal/provider/source/unversioned.py +1 -0
  631. ansible_test/_internal/provisioning.py +1 -0
  632. ansible_test/_internal/pypi_proxy.py +6 -5
  633. ansible_test/_internal/python_requirements.py +1 -0
  634. ansible_test/_internal/ssh.py +1 -0
  635. ansible_test/_internal/target.py +1 -0
  636. ansible_test/_internal/test.py +3 -2
  637. ansible_test/_internal/thread.py +1 -0
  638. ansible_test/_internal/timeout.py +1 -0
  639. ansible_test/_internal/util.py +1 -0
  640. ansible_test/_internal/util_common.py +5 -2
  641. ansible_test/_internal/venv.py +1 -0
  642. ansible_test/_util/controller/sanity/code-smell/action-plugin-docs.py +1 -0
  643. ansible_test/_util/controller/sanity/code-smell/changelog/sphinx.py +1 -0
  644. ansible_test/_util/controller/sanity/code-smell/changelog.py +1 -0
  645. ansible_test/_util/controller/sanity/code-smell/empty-init.py +1 -0
  646. ansible_test/_util/controller/sanity/code-smell/line-endings.py +1 -0
  647. ansible_test/_util/controller/sanity/code-smell/no-assert.py +1 -0
  648. ansible_test/_util/controller/sanity/code-smell/no-get-exception.py +1 -0
  649. ansible_test/_util/controller/sanity/code-smell/no-illegal-filenames.py +1 -0
  650. ansible_test/_util/controller/sanity/code-smell/no-smart-quotes.py +1 -0
  651. ansible_test/_util/controller/sanity/code-smell/replace-urlopen.py +1 -0
  652. ansible_test/_util/controller/sanity/code-smell/runtime-metadata.py +28 -1
  653. ansible_test/_util/controller/sanity/code-smell/shebang.py +1 -0
  654. ansible_test/_util/controller/sanity/code-smell/symlinks.py +1 -0
  655. ansible_test/_util/controller/sanity/code-smell/use-argspec-type-path.py +1 -0
  656. ansible_test/_util/controller/sanity/code-smell/use-compat-six.py +1 -0
  657. ansible_test/_util/controller/sanity/integration-aliases/yaml_to_json.py +2 -1
  658. ansible_test/_util/controller/sanity/pep8/current-ignore.txt +4 -0
  659. ansible_test/_util/controller/sanity/pylint/config/ansible-test-target.cfg +7 -5
  660. ansible_test/_util/controller/sanity/pylint/config/ansible-test.cfg +7 -5
  661. ansible_test/_util/controller/sanity/pylint/config/code-smell.cfg +7 -5
  662. ansible_test/_util/controller/sanity/pylint/config/collection.cfg +3 -5
  663. ansible_test/_util/controller/sanity/pylint/config/default.cfg +7 -7
  664. ansible_test/_util/controller/sanity/pylint/plugins/deprecated.py +1 -13
  665. ansible_test/_util/controller/sanity/pylint/plugins/hide_unraisable.py +1 -0
  666. ansible_test/_util/controller/sanity/pylint/plugins/string_format.py +1 -8
  667. ansible_test/_util/controller/sanity/pylint/plugins/unwanted.py +1 -8
  668. ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py +55 -28
  669. ansible_test/_util/controller/sanity/validate-modules/validate_modules/module_args.py +12 -5
  670. ansible_test/_util/controller/sanity/validate-modules/validate_modules/schema.py +13 -2
  671. ansible_test/_util/controller/sanity/validate-modules/validate_modules/utils.py +1 -0
  672. ansible_test/_util/controller/sanity/yamllint/yamllinter.py +35 -17
  673. ansible_test/_util/controller/tools/collection_detail.py +1 -0
  674. ansible_test/_util/controller/tools/yaml_to_json.py +2 -1
  675. ansible_test/_util/target/pytest/plugins/ansible_forked.py +6 -1
  676. ansible_test/_util/target/pytest/plugins/ansible_pytest_collections.py +2 -1
  677. ansible_test/_util/target/pytest/plugins/ansible_pytest_coverage.py +1 -0
  678. ansible_test/_util/target/sanity/compile/compile.py +1 -0
  679. ansible_test/_util/target/sanity/import/importer.py +15 -16
  680. ansible_test/_util/target/setup/bootstrap.sh +9 -20
  681. ansible_test/_util/target/setup/probe_cgroups.py +1 -0
  682. ansible_test/_util/target/setup/quiet_pip.py +1 -0
  683. ansible_test/_util/target/setup/requirements.py +35 -27
  684. ansible_test/_util/target/tools/virtualenvcheck.py +2 -1
  685. ansible_test/_util/target/tools/yamlcheck.py +2 -1
  686. ansible/compat/selectors.py +0 -32
  687. ansible/errors/yaml_strings.py +0 -138
  688. ansible/executor/action_write_locks.py +0 -44
  689. ansible/executor/discovery/python_target.py +0 -47
  690. ansible/executor/powershell/module_powershell_wrapper.ps1 +0 -86
  691. ansible/executor/powershell/module_script_wrapper.ps1 +0 -22
  692. ansible/module_utils/compat/importlib.py +0 -26
  693. ansible/module_utils/compat/selectors.py +0 -32
  694. ansible/module_utils/pycompat24.py +0 -73
  695. ansible/parsing/utils/jsonify.py +0 -36
  696. ansible/parsing/yaml/constructor.py +0 -178
  697. ansible/template/native_helpers.py +0 -251
  698. ansible/template/template.py +0 -43
  699. ansible/template/vars.py +0 -77
  700. ansible/utils/native_jinja.py +0 -11
  701. ansible/vars/fact_cache.py +0 -71
  702. ansible_core-2.18.5rc1.dist-info/RECORD +0 -992
  703. {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b1.dist-info}/Apache-License.txt +0 -0
  704. {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b1.dist-info}/COPYING +0 -0
  705. {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b1.dist-info}/MIT-license.txt +0 -0
  706. {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b1.dist-info}/PSF-license.txt +0 -0
  707. {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b1.dist-info}/entry_points.txt +0 -0
  708. {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b1.dist-info}/simplified_bsd.txt +0 -0
  709. {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,24 @@
1
+ from __future__ import annotations
2
+
3
+ import ast
4
+
5
+ from ansible.errors import AnsibleTypeError
6
+
7
+
8
+ def python_literal_eval(value: object, ignore_errors=False) -> object:
9
+ try:
10
+ if isinstance(value, str):
11
+ return ast.literal_eval(value)
12
+
13
+ raise AnsibleTypeError("The `value` to eval must be a string.", obj=value)
14
+ except Exception:
15
+ if ignore_errors:
16
+ return value
17
+
18
+ raise
19
+
20
+
21
+ class FilterModule(object):
22
+ @staticmethod
23
+ def filters():
24
+ return dict(python_literal_eval=python_literal_eval)
@@ -0,0 +1,33 @@
1
+ DOCUMENTATION:
2
+ name: python_literal_eval
3
+ version_added: "2.19"
4
+ short_description: evaluate a Python literal expression string
5
+ description:
6
+ - Evaluates the input string as a Python literal expression, returning the resulting data structure.
7
+ - Previous versions of Ansible applied this behavior to all template results in non-native Jinja mode.
8
+ - This filter provides a way to emulate the previous behavior.
9
+ notes:
10
+ - Directly calls Python's C(ast.literal_eval).
11
+ positional: _input
12
+ options:
13
+ _input:
14
+ description: Python literal string expression.
15
+ type: str
16
+ required: true
17
+ ignore_errors:
18
+ description: Whether to silently ignore all errors resulting from the literal_eval operation. If true, the input is silently returned unmodified when an error occurs.
19
+ type: bool
20
+ default: false
21
+
22
+ EXAMPLES: |
23
+ - name: evaluate an expression comprised only of Python literals
24
+ assert:
25
+ that: (another_var | ansible._protomatter.python_literal_eval)[1] == 2 # in 2.19 and later, the explicit python_literal_eval emulates the old templating behavior
26
+ vars:
27
+ another_var: "{{ some_var }}" # in 2.18 and earlier, indirection through templating caused implicit literal_eval, converting the value to a list
28
+ some_var: "[1, 2]" # a value that looks like a Python list literal embedded in a string
29
+
30
+ RETURN:
31
+ _value:
32
+ description: Resulting data structure.
33
+ type: raw
@@ -0,0 +1,16 @@
1
+ from __future__ import annotations
2
+
3
+ import typing as t
4
+
5
+ from ansible.module_utils._internal._datatag import AnsibleTagHelper
6
+
7
+
8
+ def tag_names(value: object) -> list[str]:
9
+ """Return a list of tag type names (if any) present on the given object."""
10
+ return sorted(tag_type.__name__ for tag_type in AnsibleTagHelper.tag_types(value))
11
+
12
+
13
+ class FilterModule:
14
+ @staticmethod
15
+ def filters() -> dict[str, t.Callable]:
16
+ return dict(tag_names=tag_names)
@@ -0,0 +1,17 @@
1
+ from __future__ import annotations
2
+
3
+ import typing as t
4
+
5
+ from ansible.plugins import accept_args_markers
6
+
7
+
8
+ @accept_args_markers
9
+ def true_type(obj: object) -> str:
10
+ """Internal filter to show the true type name of the given object, not just the base type name like the `debug` filter."""
11
+ return obj.__class__.__name__
12
+
13
+
14
+ class FilterModule(object):
15
+ @staticmethod
16
+ def filters() -> dict[str, t.Callable]:
17
+ return dict(true_type=true_type)
@@ -0,0 +1,49 @@
1
+ from __future__ import annotations
2
+
3
+ import copy
4
+ import dataclasses
5
+ import typing as t
6
+
7
+ from ansible._internal._templating._jinja_common import validate_arg_type
8
+ from ansible._internal._templating._lazy_containers import _AnsibleLazyTemplateMixin
9
+ from ansible._internal._templating._transform import _type_transform_mapping
10
+ from ansible.errors import AnsibleError
11
+
12
+
13
+ def unmask(value: object, type_names: str | list[str]) -> object:
14
+ """
15
+ Internal filter to suppress automatic type transformation in Jinja (e.g., WarningMessageDetail, DeprecationMessageDetail, ErrorDetail).
16
+ Lazy collection caching is in play - the first attempt to access a value in a given lazy container must be with unmasking in place, or the transformed value
17
+ will already be cached.
18
+ """
19
+ validate_arg_type("type_names", type_names, (str, list))
20
+
21
+ if isinstance(type_names, str):
22
+ check_type_names = [type_names]
23
+ else:
24
+ check_type_names = type_names
25
+
26
+ valid_type_names = {key.__name__ for key in _type_transform_mapping}
27
+ invalid_type_names = [type_name for type_name in check_type_names if type_name not in valid_type_names]
28
+
29
+ if invalid_type_names:
30
+ raise AnsibleError(f'Unknown type name(s): {", ".join(invalid_type_names)}', obj=type_names)
31
+
32
+ result: object
33
+
34
+ if isinstance(value, _AnsibleLazyTemplateMixin):
35
+ result = copy.copy(value)
36
+ result._lazy_options = dataclasses.replace(
37
+ result._lazy_options,
38
+ unmask_type_names=result._lazy_options.unmask_type_names | frozenset(check_type_names),
39
+ )
40
+ else:
41
+ result = value
42
+
43
+ return result
44
+
45
+
46
+ class FilterModule(object):
47
+ @staticmethod
48
+ def filters() -> dict[str, t.Callable]:
49
+ return dict(unmask=unmask)
@@ -0,0 +1,21 @@
1
+ from __future__ import annotations
2
+
3
+ from ansible.plugins.lookup import LookupBase
4
+
5
+
6
+ class LookupModule(LookupBase):
7
+ """Specialized config lookup that applies data transformations on values that config cannot."""
8
+
9
+ def run(self, terms, variables=None, **kwargs):
10
+ if not terms or not (config_name := terms[0]):
11
+ raise ValueError("config name is required")
12
+
13
+ match config_name:
14
+ case 'DISPLAY_TRACEBACK':
15
+ # since config can't expand this yet, we need the post-processed version
16
+ from ansible.module_utils._internal._traceback import traceback_for
17
+
18
+ return traceback_for()
19
+ # DTFIX-FUTURE: plumb through normal config fallback
20
+ case _:
21
+ raise ValueError(f"Unknown config name {config_name!r}.")
@@ -0,0 +1,2 @@
1
+ DOCUMENTATION:
2
+ name: config
@@ -0,0 +1,15 @@
1
+ from __future__ import annotations
2
+
3
+ import typing as t
4
+
5
+ from ansible.module_utils._internal import _datatag
6
+
7
+
8
+ def tagged(value: t.Any) -> bool:
9
+ return bool(_datatag.AnsibleTagHelper.tag_types(value))
10
+
11
+
12
+ class TestModule:
13
+ @staticmethod
14
+ def tests() -> dict[str, t.Callable]:
15
+ return dict(tagged=tagged)
@@ -0,0 +1,19 @@
1
+ DOCUMENTATION:
2
+ name: tagged
3
+ author: Ansible Core
4
+ version_added: "2.19"
5
+ short_description: does the value have a data tag
6
+ description:
7
+ - Check if the provided value has a data tag.
8
+ options:
9
+ _input:
10
+ description: A value.
11
+ type: raw
12
+
13
+ EXAMPLES: |
14
+ is_data_tagged: "{{ my_variable is ansible._protomatter.tagged }}"
15
+
16
+ RETURN:
17
+ _value:
18
+ description: Returns C(True) if the value has one or more data tags, otherwise C(False).
19
+ type: boolean
@@ -0,0 +1,18 @@
1
+ from __future__ import annotations
2
+
3
+ import typing as t
4
+
5
+ from ansible.module_utils._internal import _datatag
6
+
7
+
8
+ def tagged_with(value: t.Any, tag_name: str) -> bool:
9
+ if tag_type := _datatag._known_tag_type_map.get(tag_name):
10
+ return tag_type.is_tagged_on(value)
11
+
12
+ raise ValueError(f"Unknown tag name {tag_name!r}.")
13
+
14
+
15
+ class TestModule:
16
+ @staticmethod
17
+ def tests() -> dict[str, t.Callable]:
18
+ return dict(tagged_with=tagged_with)
@@ -0,0 +1,19 @@
1
+ DOCUMENTATION:
2
+ name: tagged_with
3
+ author: Ansible Core
4
+ version_added: "2.19"
5
+ short_description: does the value have the specified data tag
6
+ description:
7
+ - Check if the provided value has the specified data tag.
8
+ options:
9
+ _input:
10
+ description: A value.
11
+ type: raw
12
+
13
+ EXAMPLES: |
14
+ is_data_tagged: "{{ my_variable is ansible._protomatter.tagged_with('Origin') }}"
15
+
16
+ RETURN:
17
+ _value:
18
+ description: Returns C(True) if the value has the specified data tag, otherwise C(False).
19
+ type: boolean
ansible/cli/__init__.py CHANGED
@@ -7,8 +7,22 @@ from __future__ import annotations
7
7
 
8
8
  import locale
9
9
  import os
10
+ import signal
10
11
  import sys
11
12
 
13
+
14
+ # We overload the ``ansible`` adhoc command to provide the functionality for
15
+ # ``SSH_ASKPASS``. This code is here, and not in ``adhoc.py`` to bypass
16
+ # unnecessary code. The program provided to ``SSH_ASKPASS`` can only be invoked
17
+ # as a singular command, ``python -m`` doesn't work for that use case, and we
18
+ # aren't adding a new entrypoint at this time. Assume that if we are executing
19
+ # and there is only a single item in argv plus the executable, and the env var
20
+ # is set we are in ``SSH_ASKPASS`` mode
21
+ if 1 <= len(sys.argv) <= 2 and os.path.basename(sys.argv[0]) == "ansible" and os.getenv('_ANSIBLE_SSH_ASKPASS_SHM'):
22
+ from ansible.cli import _ssh_askpass
23
+ _ssh_askpass.main()
24
+
25
+
12
26
  # Used for determining if the system is running a new enough python version
13
27
  # and should only restrict on our documented minimum versions
14
28
  if sys.version_info < (3, 11):
@@ -63,18 +77,7 @@ def initialize_locale():
63
77
  initialize_locale()
64
78
 
65
79
 
66
- from importlib.metadata import version
67
- from ansible.module_utils.compat.version import LooseVersion
68
-
69
- # Used for determining if the system is running a new enough Jinja2 version
70
- # and should only restrict on our documented minimum versions
71
- jinja2_version = version('jinja2')
72
- if jinja2_version < LooseVersion('3.0'):
73
- raise SystemExit(
74
- 'ERROR: Ansible requires Jinja2 3.0 or newer on the controller. '
75
- 'Current version: %s' % jinja2_version
76
- )
77
-
80
+ import atexit
78
81
  import errno
79
82
  import getpass
80
83
  import subprocess
@@ -82,30 +85,36 @@ import traceback
82
85
  from abc import ABC, abstractmethod
83
86
  from pathlib import Path
84
87
 
88
+ from ansible import _internal # do not remove or defer; ensures controller-specific state is set early
89
+
90
+ _internal.setup()
91
+
85
92
  try:
86
93
  from ansible import constants as C
87
94
  from ansible.utils.display import Display
88
95
  display = Display()
89
- except Exception as e:
90
- print('ERROR: %s' % e, file=sys.stderr)
96
+ except Exception as ex:
97
+ print(f'ERROR: {ex}\n\n{"".join(traceback.format_exception(ex))}', file=sys.stderr)
91
98
  sys.exit(5)
92
99
 
100
+
93
101
  from ansible import context
94
102
  from ansible.cli.arguments import option_helpers as opt_help
95
- from ansible.errors import AnsibleError, AnsibleOptionsError, AnsibleParserError
103
+ from ansible.errors import AnsibleError, ExitCode
96
104
  from ansible.inventory.manager import InventoryManager
97
105
  from ansible.module_utils.six import string_types
98
106
  from ansible.module_utils.common.text.converters import to_bytes, to_text
99
107
  from ansible.module_utils.common.collections import is_sequence
100
108
  from ansible.module_utils.common.file import is_executable
109
+ from ansible.module_utils.common.process import get_bin_path
101
110
  from ansible.parsing.dataloader import DataLoader
102
- from ansible.parsing.vault import PromptVaultSecret, get_file_vault_secret
111
+ from ansible.parsing.vault import PromptVaultSecret, get_file_vault_secret, VaultSecretsContext
103
112
  from ansible.plugins.loader import add_all_plugin_dirs, init_plugin_loader
104
113
  from ansible.release import __version__
114
+ from ansible.utils._ssh_agent import SshAgentClient
105
115
  from ansible.utils.collection_loader import AnsibleCollectionConfig
106
116
  from ansible.utils.collection_loader._collection_finder import _get_collection_name_from_path
107
117
  from ansible.utils.path import unfrackpath
108
- from ansible.utils.unsafe_proxy import to_unsafe_text
109
118
  from ansible.vars.manager import VariableManager
110
119
 
111
120
  try:
@@ -115,8 +124,79 @@ except ImportError:
115
124
  HAS_ARGCOMPLETE = False
116
125
 
117
126
 
127
+ _SSH_AGENT_STDOUT_READ_TIMEOUT = 5 # seconds
128
+
129
+
130
+ def _ssh_agent_timeout_handler(signum, frame):
131
+ raise TimeoutError
132
+
133
+
134
+ def _launch_ssh_agent() -> None:
135
+ ssh_agent_cfg = C.config.get_config_value('SSH_AGENT')
136
+ match ssh_agent_cfg:
137
+ case 'none':
138
+ display.debug('SSH_AGENT set to none')
139
+ return
140
+ case 'auto':
141
+ try:
142
+ ssh_agent_bin = get_bin_path('ssh-agent', required=True)
143
+ except ValueError as e:
144
+ raise AnsibleError('SSH_AGENT set to auto, but cannot find ssh-agent binary') from e
145
+ ssh_agent_dir = os.path.join(C.DEFAULT_LOCAL_TMP, 'ssh_agent')
146
+ os.mkdir(ssh_agent_dir, 0o700)
147
+ sock = os.path.join(ssh_agent_dir, 'agent.sock')
148
+ display.vvv('SSH_AGENT: starting...')
149
+ try:
150
+ p = subprocess.Popen(
151
+ [ssh_agent_bin, '-D', '-s', '-a', sock],
152
+ stdin=subprocess.PIPE,
153
+ stdout=subprocess.PIPE,
154
+ stderr=subprocess.PIPE,
155
+ )
156
+ except OSError as e:
157
+ raise AnsibleError(
158
+ f'Could not start ssh-agent: {e}'
159
+ ) from e
160
+
161
+ if p.poll() is not None:
162
+ raise AnsibleError(
163
+ f'Could not start ssh-agent: rc={p.returncode} stderr="{p.stderr.read().decode()}"'
164
+ )
165
+
166
+ old_sigalrm_handler = signal.signal(signal.SIGALRM, _ssh_agent_timeout_handler)
167
+ signal.alarm(_SSH_AGENT_STDOUT_READ_TIMEOUT)
168
+ try:
169
+ stdout = p.stdout.read(13)
170
+ except TimeoutError:
171
+ stdout = b''
172
+ finally:
173
+ signal.alarm(0)
174
+ signal.signal(signal.SIGALRM, old_sigalrm_handler)
175
+
176
+ if stdout != b'SSH_AUTH_SOCK':
177
+ display.warning(
178
+ f'The first 13 characters of stdout did not match the '
179
+ f'expected SSH_AUTH_SOCK. This may not be the right binary, '
180
+ f'or an incompatible agent: {stdout.decode()}'
181
+ )
182
+ display.vvv(f'SSH_AGENT: ssh-agent[{p.pid}] started and bound to {sock}')
183
+ atexit.register(p.terminate)
184
+ case _:
185
+ sock = ssh_agent_cfg
186
+
187
+ try:
188
+ with SshAgentClient(sock) as client:
189
+ client.list()
190
+ except Exception as e:
191
+ raise AnsibleError(
192
+ f'Could not communicate with ssh-agent using auth sock {sock}: {e}'
193
+ ) from e
194
+
195
+ os.environ['SSH_AUTH_SOCK'] = os.environ['ANSIBLE_SSH_AGENT'] = sock
196
+
197
+
118
198
  class CLI(ABC):
119
- ''' code behind bin/ansible* programs '''
199
+ """ code behind bin/ansible* programs """
120
200
 
121
201
  PAGER = C.config.get_config_value('PAGER')
122
202
 
@@ -124,6 +204,7 @@ class CLI(ABC):
124
204
  # -S (chop long lines) -X (disable termcap init and de-init)
125
205
  LESS_OPTS = 'FRSX'
126
206
  SKIP_INVENTORY_DEFAULTS = False
207
+ USES_CONNECTION = False
127
208
 
128
209
  def __init__(self, args, callback=None):
129
210
  """
@@ -137,6 +218,9 @@ class CLI(ABC):
137
218
  self.parser = None
138
219
  self.callback = callback
139
220
 
221
+ self.show_devel_warning()
222
+
223
+ def show_devel_warning(self) -> None:
140
224
  if C.DEVEL_WARNING and __version__.endswith('dev0'):
141
225
  display.warning(
142
226
  'You are running the development version of Ansible. You should only run Ansible from "devel" if '
@@ -208,7 +292,7 @@ class CLI(ABC):
208
292
  @staticmethod
209
293
  def setup_vault_secrets(loader, vault_ids, vault_password_files=None,
210
294
  ask_vault_pass=None, create_new_password=False,
211
- auto_prompt=True):
295
+ auto_prompt=True, initialize_context=True):
212
296
  # list of tuples
213
297
  vault_secrets = []
214
298
 
@@ -305,24 +389,22 @@ class CLI(ABC):
305
389
  if last_exception and not found_vault_secret:
306
390
  raise last_exception
307
391
 
392
+ if initialize_context:
393
+ VaultSecretsContext.initialize(VaultSecretsContext(vault_secrets))
394
+
308
395
  return vault_secrets
309
396
 
310
397
  @staticmethod
311
- def _get_secret(prompt):
312
-
313
- secret = getpass.getpass(prompt=prompt)
314
- if secret:
315
- secret = to_unsafe_text(secret)
316
- return secret
398
+ def _get_secret(prompt: str) -> str:
399
+ return getpass.getpass(prompt=prompt)
317
400
 
318
401
  @staticmethod
319
402
  def ask_passwords():
320
- ''' prompt for connection and become passwords if needed '''
403
+ """ prompt for connection and become passwords if needed """
321
404
 
322
405
  op = context.CLIARGS
323
406
  sshpass = None
324
407
  becomepass = None
325
- become_prompt = ''
326
408
 
327
409
  become_prompt_method = "BECOME" if C.AGNOSTIC_BECOME_PROMPT else op['become_method'].upper()
328
410
 
@@ -344,10 +426,10 @@ class CLI(ABC):
344
426
  except EOFError:
345
427
  pass
346
428
 
347
- return (sshpass, becomepass)
429
+ return sshpass, becomepass
348
430
 
349
431
  def validate_conflicts(self, op, runas_opts=False, fork_opts=False):
350
- ''' check for conflicting options '''
432
+ """ check for conflicting options """
351
433
 
352
434
  if fork_opts:
353
435
  if op.forks < 1:
@@ -459,7 +541,7 @@ class CLI(ABC):
459
541
 
460
542
  @staticmethod
461
543
  def version_info(gitinfo=False):
462
- ''' return full ansible version info '''
544
+ """ return full ansible version info """
463
545
  if gitinfo:
464
546
  # expensive call, user with care
465
547
  ansible_version_string = opt_help.version()
@@ -485,7 +567,7 @@ class CLI(ABC):
485
567
 
486
568
  @staticmethod
487
569
  def pager(text):
488
- ''' find reasonable way to display text '''
570
+ """ find reasonable way to display text """
489
571
  # this is a much simpler form of what is in pydoc.py
490
572
  if not sys.stdout.isatty():
491
573
  display.display(text, screen_only=True)
@@ -504,7 +586,7 @@ class CLI(ABC):
504
586
 
505
587
  @staticmethod
506
588
  def pager_pipe(text):
507
- ''' pipe text through a pager '''
589
+ """ pipe text through a pager """
508
590
  if 'less' in CLI.PAGER:
509
591
  os.environ['LESS'] = CLI.LESS_OPTS
510
592
  try:
@@ -515,8 +597,7 @@ class CLI(ABC):
515
597
  except KeyboardInterrupt:
516
598
  pass
517
599
 
518
- @staticmethod
519
- def _play_prereqs():
600
+ def _play_prereqs(self):
520
601
  # TODO: evaluate moving all of the code that touches ``AnsibleCollectionConfig``
521
602
  # into ``init_plugin_loader`` so that we can specifically remove
522
603
  # ``AnsibleCollectionConfig.playbook_paths`` to make it immutable after instantiation
@@ -547,6 +628,12 @@ class CLI(ABC):
547
628
  auto_prompt=False)
548
629
  loader.set_vault_secrets(vault_secrets)
549
630
 
631
+ if self.USES_CONNECTION:
632
+ try:
633
+ _launch_ssh_agent()
634
+ except Exception as e:
635
+ raise AnsibleError('Failed to launch ssh agent', orig_exc=e)
636
+
550
637
  # create the inventory, and filter it based on the subset specified (if any)
551
638
  inventory = InventoryManager(loader=loader, sources=options['inventory'], cache=(not options.get('flush_cache')))
552
639
 
@@ -554,8 +641,19 @@ class CLI(ABC):
554
641
  # the code, ensuring a consistent view of global variables
555
642
  variable_manager = VariableManager(loader=loader, inventory=inventory, version_info=CLI.version_info(gitinfo=False))
556
643
 
644
+ # flush fact cache if requested
645
+ if options['flush_cache']:
646
+ CLI._flush_cache(inventory, variable_manager)
647
+
557
648
  return loader, inventory, variable_manager
558
649
 
650
+ @staticmethod
651
+ def _flush_cache(inventory, variable_manager):
652
+ variable_manager.clear_facts('localhost')
653
+ for host in inventory.list_hosts():
654
+ hostname = host.get_name()
655
+ variable_manager.clear_facts(hostname)
656
+
559
657
  @staticmethod
560
658
  def get_host_list(inventory, subset, pattern='all'):
561
659
 
@@ -575,10 +673,9 @@ class CLI(ABC):
575
673
  return hosts
576
674
 
577
675
  @staticmethod
578
- def get_password_from_file(pwd_file):
579
-
676
+ def get_password_from_file(pwd_file: str) -> str:
580
677
  b_pwd_file = to_bytes(pwd_file)
581
- secret = None
678
+
582
679
  if b_pwd_file == b'-':
583
680
  # ensure its read as bytes
584
681
  secret = sys.stdin.buffer.read()
@@ -598,14 +695,13 @@ class CLI(ABC):
598
695
 
599
696
  stdout, stderr = p.communicate()
600
697
  if p.returncode != 0:
601
- raise AnsibleError("The password script %s returned an error (rc=%s): %s" % (pwd_file, p.returncode, stderr))
698
+ raise AnsibleError("The password script %s returned an error (rc=%s): %s" % (pwd_file, p.returncode, to_text(stderr)))
602
699
  secret = stdout
603
700
 
604
701
  else:
605
702
  try:
606
- f = open(b_pwd_file, "rb")
607
- secret = f.read().strip()
608
- f.close()
703
+ with open(b_pwd_file, "rb") as password_file:
704
+ secret = password_file.read().strip()
609
705
  except (OSError, IOError) as e:
610
706
  raise AnsibleError("Could not read password file %s: %s" % (pwd_file, e))
611
707
 
@@ -614,7 +710,7 @@ class CLI(ABC):
614
710
  if not secret:
615
711
  raise AnsibleError('Empty password was provided from file (%s)' % pwd_file)
616
712
 
617
- return to_unsafe_text(secret)
713
+ return to_text(secret)
618
714
 
619
715
  @classmethod
620
716
  def cli_executor(cls, args=None):
@@ -635,54 +731,22 @@ class CLI(ABC):
635
731
  else:
636
732
  display.debug("Created the '%s' directory" % ansible_dir)
637
733
 
638
- try:
639
- args = [to_text(a, errors='surrogate_or_strict') for a in args]
640
- except UnicodeError:
641
- display.error('Command line args are not in utf-8, unable to continue. Ansible currently only understands utf-8')
642
- display.display(u"The full traceback was:\n\n%s" % to_text(traceback.format_exc()))
643
- exit_code = 6
644
- else:
645
- cli = cls(args)
646
- exit_code = cli.run()
647
-
648
- except AnsibleOptionsError as e:
649
- cli.parser.print_help()
650
- display.error(to_text(e), wrap_text=False)
651
- exit_code = 5
652
- except AnsibleParserError as e:
653
- display.error(to_text(e), wrap_text=False)
654
- exit_code = 4
655
- # TQM takes care of these, but leaving comment to reserve the exit codes
656
- # except AnsibleHostUnreachable as e:
657
- # display.error(str(e))
658
- # exit_code = 3
659
- # except AnsibleHostFailed as e:
660
- # display.error(str(e))
661
- # exit_code = 2
662
- except AnsibleError as e:
663
- display.error(to_text(e), wrap_text=False)
664
- exit_code = 1
734
+ cli = cls(args)
735
+ exit_code = cli.run()
736
+ except AnsibleError as ex:
737
+ display.error(ex)
738
+ exit_code = ex._exit_code
665
739
  except KeyboardInterrupt:
666
740
  display.error("User interrupted execution")
667
- exit_code = 99
668
- except Exception as e:
669
- if C.DEFAULT_DEBUG:
670
- # Show raw stacktraces in debug mode, It also allow pdb to
671
- # enter post mortem mode.
672
- raise
673
- have_cli_options = bool(context.CLIARGS)
674
- display.error("Unexpected Exception, this is probably a bug: %s" % to_text(e), wrap_text=False)
675
- if not have_cli_options or have_cli_options and context.CLIARGS['verbosity'] > 2:
676
- log_only = False
677
- if hasattr(e, 'orig_exc'):
678
- display.vvv('\nexception type: %s' % to_text(type(e.orig_exc)))
679
- why = to_text(e.orig_exc)
680
- if to_text(e) != why:
681
- display.vvv('\noriginal msg: %s' % why)
682
- else:
683
- display.display("to see the full traceback, use -vvv")
684
- log_only = True
685
- display.display(u"the full traceback was:\n\n%s" % to_text(traceback.format_exc()), log_only=log_only)
686
- exit_code = 250
741
+ exit_code = ExitCode.KEYBOARD_INTERRUPT
742
+ except Exception as ex:
743
+ try:
744
+ raise AnsibleError("Unexpected Exception, this is probably a bug.") from ex
745
+ except AnsibleError as ex2:
746
+ # DTFIX-RELEASE: clean this up so we're not hacking the internals- re-wrap in an AnsibleCLIUnhandledError that always shows TB, or?
747
+ from ansible.module_utils._internal import _traceback
748
+ _traceback._is_traceback_enabled = lambda *_args, **_kwargs: True
749
+ display.error(ex2)
750
+ exit_code = ExitCode.UNKNOWN_ERROR
687
751
 
688
752
  sys.exit(exit_code)