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