ansible-core 2.18.7rc1__py3-none-any.whl → 2.19.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ansible-core might be problematic. Click here for more details.

Files changed (757) hide show
  1. ansible/_internal/__init__.py +53 -0
  2. ansible/_internal/_ansiballz/__init__.py +0 -0
  3. ansible/_internal/_ansiballz/_builder.py +101 -0
  4. ansible/_internal/_ansiballz/_wrapper.py +262 -0
  5. ansible/_internal/_collection_proxy.py +47 -0
  6. ansible/_internal/_datatag/__init__.py +0 -0
  7. ansible/_internal/_datatag/_tags.py +130 -0
  8. ansible/_internal/_datatag/_utils.py +19 -0
  9. ansible/_internal/_datatag/_wrappers.py +33 -0
  10. ansible/_internal/_errors/__init__.py +0 -0
  11. ansible/_internal/_errors/_alarm_timeout.py +66 -0
  12. ansible/_internal/_errors/_captured.py +123 -0
  13. ansible/_internal/_errors/_error_factory.py +89 -0
  14. ansible/_internal/_errors/_error_utils.py +240 -0
  15. ansible/_internal/_errors/_handler.py +91 -0
  16. ansible/_internal/_errors/_task_timeout.py +28 -0
  17. ansible/_internal/_event_formatting.py +127 -0
  18. ansible/_internal/_json/__init__.py +214 -0
  19. ansible/_internal/_json/_legacy_encoder.py +34 -0
  20. ansible/_internal/_json/_profiles/__init__.py +0 -0
  21. ansible/_internal/_json/_profiles/_cache_persistence.py +57 -0
  22. ansible/_internal/_json/_profiles/_inventory_legacy.py +40 -0
  23. ansible/_internal/_json/_profiles/_legacy.py +189 -0
  24. ansible/_internal/_locking.py +21 -0
  25. ansible/_internal/_plugins/__init__.py +0 -0
  26. ansible/_internal/_plugins/_cache.py +57 -0
  27. ansible/_internal/_ssh/__init__.py +0 -0
  28. ansible/_internal/_ssh/_agent_launch.py +91 -0
  29. ansible/_internal/_ssh/_ssh_agent.py +619 -0
  30. ansible/_internal/_task.py +78 -0
  31. ansible/_internal/_templating/__init__.py +12 -0
  32. ansible/_internal/_templating/_access.py +86 -0
  33. ansible/_internal/_templating/_chain_templar.py +63 -0
  34. ansible/_internal/_templating/_datatag.py +95 -0
  35. ansible/_internal/_templating/_engine.py +592 -0
  36. ansible/_internal/_templating/_errors.py +28 -0
  37. ansible/_internal/_templating/_jinja_bits.py +1106 -0
  38. ansible/_internal/_templating/_jinja_common.py +323 -0
  39. ansible/_internal/_templating/_jinja_patches.py +44 -0
  40. ansible/_internal/_templating/_jinja_plugins.py +375 -0
  41. ansible/_internal/_templating/_lazy_containers.py +633 -0
  42. ansible/_internal/_templating/_marker_behaviors.py +103 -0
  43. ansible/_internal/_templating/_template_vars.py +72 -0
  44. ansible/_internal/_templating/_transform.py +70 -0
  45. ansible/_internal/_templating/_utils.py +108 -0
  46. ansible/_internal/_testing.py +26 -0
  47. ansible/_internal/_wrapt.py +1052 -0
  48. ansible/_internal/_yaml/__init__.py +0 -0
  49. ansible/_internal/_yaml/_constructor.py +240 -0
  50. ansible/_internal/_yaml/_dumper.py +70 -0
  51. ansible/_internal/_yaml/_errors.py +166 -0
  52. ansible/_internal/_yaml/_loader.py +66 -0
  53. ansible/_internal/ansible_collections/ansible/_protomatter/README.md +11 -0
  54. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/action/debug.py +36 -0
  55. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/apply_trust.py +19 -0
  56. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/dump_object.py +27 -0
  57. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/finalize.py +16 -0
  58. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/origin.py +18 -0
  59. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/python_literal_eval.py +24 -0
  60. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/python_literal_eval.yml +33 -0
  61. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/tag_names.py +16 -0
  62. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/true_type.py +17 -0
  63. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/unmask.py +49 -0
  64. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/lookup/config.py +21 -0
  65. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/lookup/config.yml +2 -0
  66. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged.py +15 -0
  67. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged.yml +19 -0
  68. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged_with.py +18 -0
  69. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged_with.yml +19 -0
  70. ansible/cli/__init__.py +93 -104
  71. ansible/cli/_ssh_askpass.py +54 -0
  72. ansible/cli/adhoc.py +20 -10
  73. ansible/cli/arguments/option_helpers.py +163 -10
  74. ansible/cli/config.py +43 -68
  75. ansible/cli/console.py +13 -11
  76. ansible/cli/doc.py +134 -77
  77. ansible/cli/galaxy.py +27 -20
  78. ansible/cli/inventory.py +28 -28
  79. ansible/cli/playbook.py +4 -12
  80. ansible/cli/pull.py +6 -3
  81. ansible/cli/scripts/ansible_connection_cli_stub.py +7 -7
  82. ansible/cli/vault.py +12 -11
  83. ansible/compat/__init__.py +2 -2
  84. ansible/compat/importlib_resources.py +9 -12
  85. ansible/config/base.yml +218 -133
  86. ansible/config/manager.py +220 -159
  87. ansible/constants.py +2 -65
  88. ansible/errors/__init__.py +350 -256
  89. ansible/executor/interpreter_discovery.py +28 -149
  90. ansible/executor/module_common.py +480 -514
  91. ansible/executor/play_iterator.py +22 -27
  92. ansible/executor/playbook_executor.py +11 -11
  93. ansible/executor/powershell/async_watchdog.ps1 +97 -102
  94. ansible/executor/powershell/async_wrapper.ps1 +204 -153
  95. ansible/executor/powershell/become_wrapper.ps1 +107 -144
  96. ansible/executor/powershell/bootstrap_wrapper.ps1 +46 -9
  97. ansible/executor/powershell/coverage_wrapper.ps1 +91 -135
  98. ansible/executor/powershell/exec_wrapper.ps1 +675 -196
  99. ansible/executor/powershell/module_manifest.py +469 -265
  100. ansible/executor/powershell/module_wrapper.ps1 +195 -186
  101. ansible/executor/powershell/powershell_expand_user.ps1 +20 -0
  102. ansible/executor/powershell/powershell_mkdtemp.ps1 +17 -0
  103. ansible/executor/powershell/psrp_fetch_file.ps1 +41 -0
  104. ansible/executor/powershell/psrp_put_file.ps1 +122 -0
  105. ansible/executor/powershell/winrm_fetch_file.ps1 +46 -0
  106. ansible/executor/powershell/winrm_put_file.ps1 +36 -0
  107. ansible/executor/process/worker.py +139 -149
  108. ansible/executor/stats.py +5 -5
  109. ansible/executor/task_executor.py +270 -297
  110. ansible/executor/task_queue_manager.py +135 -137
  111. ansible/executor/task_result.py +182 -79
  112. ansible/galaxy/__init__.py +2 -2
  113. ansible/galaxy/api.py +26 -25
  114. ansible/galaxy/collection/__init__.py +6 -14
  115. ansible/galaxy/collection/concrete_artifact_manager.py +12 -21
  116. ansible/galaxy/dependency_resolution/dataclasses.py +14 -4
  117. ansible/galaxy/dependency_resolution/providers.py +4 -4
  118. ansible/galaxy/dependency_resolution/reporters.py +81 -0
  119. ansible/galaxy/role.py +6 -10
  120. ansible/galaxy/token.py +28 -21
  121. ansible/inventory/data.py +47 -57
  122. ansible/inventory/group.py +50 -73
  123. ansible/inventory/helpers.py +9 -0
  124. ansible/inventory/host.py +37 -54
  125. ansible/inventory/manager.py +79 -34
  126. ansible/keyword_desc.yml +1 -1
  127. ansible/module_utils/_internal/__init__.py +55 -0
  128. ansible/module_utils/_internal/_ambient_context.py +58 -0
  129. ansible/module_utils/_internal/_ansiballz/__init__.py +0 -0
  130. ansible/module_utils/_internal/_ansiballz/_extensions/__init__.py +0 -0
  131. ansible/module_utils/_internal/_ansiballz/_extensions/_coverage.py +45 -0
  132. ansible/module_utils/_internal/_ansiballz/_extensions/_pydevd.py +62 -0
  133. ansible/module_utils/_internal/_ansiballz/_loader.py +81 -0
  134. ansible/module_utils/_internal/_ansiballz/_respawn.py +32 -0
  135. ansible/module_utils/_internal/_ansiballz/_respawn_wrapper.py +23 -0
  136. ansible/module_utils/_internal/_concurrent/_daemon_threading.py +1 -0
  137. ansible/module_utils/_internal/_dataclass_validation.py +217 -0
  138. ansible/module_utils/_internal/_datatag/__init__.py +961 -0
  139. ansible/module_utils/_internal/_datatag/_tags.py +16 -0
  140. ansible/module_utils/_internal/_debugging.py +31 -0
  141. ansible/module_utils/_internal/_deprecator.py +157 -0
  142. ansible/module_utils/_internal/_errors.py +101 -0
  143. ansible/module_utils/_internal/_event_utils.py +61 -0
  144. ansible/module_utils/_internal/_json/__init__.py +63 -0
  145. ansible/module_utils/_internal/_json/_legacy_encoder.py +26 -0
  146. ansible/module_utils/_internal/_json/_profiles/__init__.py +428 -0
  147. ansible/module_utils/_internal/_json/_profiles/_fallback_to_str.py +73 -0
  148. ansible/module_utils/_internal/_json/_profiles/_module_legacy_c2m.py +33 -0
  149. ansible/module_utils/_internal/_json/_profiles/_module_legacy_m2c.py +37 -0
  150. ansible/module_utils/_internal/_json/_profiles/_module_modern_c2m.py +35 -0
  151. ansible/module_utils/_internal/_json/_profiles/_module_modern_m2c.py +33 -0
  152. ansible/module_utils/_internal/_json/_profiles/_tagless.py +52 -0
  153. ansible/module_utils/_internal/_messages.py +130 -0
  154. ansible/module_utils/_internal/_patches/__init__.py +66 -0
  155. ansible/module_utils/_internal/_patches/_dataclass_annotation_patch.py +53 -0
  156. ansible/module_utils/_internal/_patches/_socket_patch.py +34 -0
  157. ansible/module_utils/_internal/_patches/_sys_intern_patch.py +34 -0
  158. ansible/module_utils/_internal/_plugin_info.py +38 -0
  159. ansible/module_utils/_internal/_stack.py +22 -0
  160. ansible/module_utils/_internal/_testing.py +0 -0
  161. ansible/module_utils/_internal/_text_utils.py +6 -0
  162. ansible/module_utils/_internal/_traceback.py +92 -0
  163. ansible/module_utils/_internal/_validation.py +14 -0
  164. ansible/module_utils/ansible_release.py +2 -2
  165. ansible/module_utils/api.py +1 -2
  166. ansible/module_utils/basic.py +303 -202
  167. ansible/module_utils/common/_utils.py +24 -28
  168. ansible/module_utils/common/arg_spec.py +8 -3
  169. ansible/module_utils/common/collections.py +7 -2
  170. ansible/module_utils/common/dict_transformations.py +2 -2
  171. ansible/module_utils/common/file.py +2 -2
  172. ansible/module_utils/common/json.py +90 -84
  173. ansible/module_utils/common/locale.py +2 -2
  174. ansible/module_utils/common/parameters.py +27 -24
  175. ansible/module_utils/common/process.py +2 -3
  176. ansible/module_utils/common/respawn.py +11 -33
  177. ansible/module_utils/common/sentinel.py +66 -0
  178. ansible/module_utils/common/sys_info.py +8 -8
  179. ansible/module_utils/common/text/converters.py +16 -37
  180. ansible/module_utils/common/validation.py +35 -24
  181. ansible/module_utils/common/warnings.py +143 -25
  182. ansible/module_utils/common/yaml.py +29 -3
  183. ansible/module_utils/compat/datetime.py +33 -21
  184. ansible/module_utils/compat/paramiko.py +21 -10
  185. ansible/module_utils/compat/typing.py +6 -5
  186. ansible/module_utils/connection.py +10 -13
  187. ansible/module_utils/csharp/Ansible.Basic.cs +15 -12
  188. ansible/module_utils/csharp/Ansible.Become.cs +1 -0
  189. ansible/module_utils/csharp/Ansible.Privilege.cs +2 -2
  190. ansible/module_utils/csharp/Ansible._Async.cs +517 -0
  191. ansible/module_utils/datatag.py +49 -0
  192. ansible/module_utils/distro/__init__.py +2 -2
  193. ansible/module_utils/facts/ansible_collector.py +4 -5
  194. ansible/module_utils/facts/collector.py +13 -14
  195. ansible/module_utils/facts/compat.py +4 -4
  196. ansible/module_utils/facts/default_collectors.py +1 -1
  197. ansible/module_utils/facts/hardware/aix.py +34 -0
  198. ansible/module_utils/facts/hardware/base.py +2 -2
  199. ansible/module_utils/facts/hardware/darwin.py +1 -3
  200. ansible/module_utils/facts/hardware/freebsd.py +2 -2
  201. ansible/module_utils/facts/hardware/linux.py +5 -5
  202. ansible/module_utils/facts/namespace.py +1 -1
  203. ansible/module_utils/facts/network/base.py +1 -1
  204. ansible/module_utils/facts/network/fc_wwn.py +1 -2
  205. ansible/module_utils/facts/network/iscsi.py +1 -2
  206. ansible/module_utils/facts/network/nvme.py +1 -2
  207. ansible/module_utils/facts/other/facter.py +2 -3
  208. ansible/module_utils/facts/other/ohai.py +2 -3
  209. ansible/module_utils/facts/sysctl.py +4 -6
  210. ansible/module_utils/facts/system/apparmor.py +1 -2
  211. ansible/module_utils/facts/system/caps.py +3 -3
  212. ansible/module_utils/facts/system/chroot.py +1 -2
  213. ansible/module_utils/facts/system/cmdline.py +1 -2
  214. ansible/module_utils/facts/system/date_time.py +5 -3
  215. ansible/module_utils/facts/system/distribution.py +27 -13
  216. ansible/module_utils/facts/system/dns.py +1 -1
  217. ansible/module_utils/facts/system/env.py +1 -2
  218. ansible/module_utils/facts/system/fips.py +7 -20
  219. ansible/module_utils/facts/system/loadavg.py +1 -2
  220. ansible/module_utils/facts/system/local.py +2 -3
  221. ansible/module_utils/facts/system/lsb.py +1 -2
  222. ansible/module_utils/facts/system/pkg_mgr.py +1 -2
  223. ansible/module_utils/facts/system/platform.py +1 -2
  224. ansible/module_utils/facts/system/python.py +1 -2
  225. ansible/module_utils/facts/system/selinux.py +1 -1
  226. ansible/module_utils/facts/system/service_mgr.py +1 -2
  227. ansible/module_utils/facts/system/ssh_pub_keys.py +1 -1
  228. ansible/module_utils/facts/system/systemd.py +1 -1
  229. ansible/module_utils/facts/system/user.py +1 -2
  230. ansible/module_utils/facts/utils.py +3 -3
  231. ansible/module_utils/facts/virtual/base.py +1 -1
  232. ansible/module_utils/facts/virtual/linux.py +3 -3
  233. ansible/module_utils/facts/virtual/sunos.py +3 -15
  234. ansible/module_utils/facts/virtual/sysctl.py +3 -16
  235. ansible/module_utils/json_utils.py +2 -2
  236. ansible/module_utils/parsing/convert_bool.py +7 -1
  237. ansible/module_utils/powershell/Ansible.ModuleUtils.AddType.psm1 +1 -1
  238. ansible/module_utils/powershell/Ansible.ModuleUtils.CamelConversion.psm1 +1 -1
  239. ansible/module_utils/powershell/Ansible.ModuleUtils.CommandUtil.psm1 +1 -1
  240. ansible/module_utils/powershell/Ansible.ModuleUtils.WebRequest.psm1 +1 -1
  241. ansible/module_utils/service.py +21 -31
  242. ansible/module_utils/splitter.py +7 -7
  243. ansible/module_utils/testing.py +31 -0
  244. ansible/module_utils/urls.py +64 -35
  245. ansible/modules/add_host.py +4 -4
  246. ansible/modules/apt.py +69 -49
  247. ansible/modules/apt_key.py +19 -12
  248. ansible/modules/apt_repository.py +32 -51
  249. ansible/modules/assemble.py +16 -14
  250. ansible/modules/assert.py +4 -4
  251. ansible/modules/async_status.py +24 -24
  252. ansible/modules/async_wrapper.py +20 -25
  253. ansible/modules/blockinfile.py +6 -7
  254. ansible/modules/command.py +13 -20
  255. ansible/modules/copy.py +60 -147
  256. ansible/modules/cron.py +24 -21
  257. ansible/modules/deb822_repository.py +8 -9
  258. ansible/modules/debconf.py +5 -5
  259. ansible/modules/debug.py +4 -4
  260. ansible/modules/dnf.py +8 -8
  261. ansible/modules/dnf5.py +39 -13
  262. ansible/modules/dpkg_selections.py +4 -4
  263. ansible/modules/expect.py +13 -15
  264. ansible/modules/fail.py +4 -4
  265. ansible/modules/fetch.py +4 -4
  266. ansible/modules/file.py +184 -144
  267. ansible/modules/find.py +22 -20
  268. ansible/modules/gather_facts.py +3 -3
  269. ansible/modules/get_url.py +77 -54
  270. ansible/modules/getent.py +7 -9
  271. ansible/modules/git.py +38 -38
  272. ansible/modules/group.py +6 -6
  273. ansible/modules/group_by.py +4 -4
  274. ansible/modules/hostname.py +15 -32
  275. ansible/modules/import_playbook.py +6 -6
  276. ansible/modules/import_role.py +6 -6
  277. ansible/modules/import_tasks.py +6 -6
  278. ansible/modules/include_role.py +6 -6
  279. ansible/modules/include_tasks.py +6 -6
  280. ansible/modules/include_vars.py +6 -6
  281. ansible/modules/iptables.py +86 -73
  282. ansible/modules/known_hosts.py +22 -24
  283. ansible/modules/lineinfile.py +5 -5
  284. ansible/modules/meta.py +4 -4
  285. ansible/modules/mount_facts.py +2 -2
  286. ansible/modules/package.py +10 -4
  287. ansible/modules/package_facts.py +22 -10
  288. ansible/modules/pause.py +6 -6
  289. ansible/modules/ping.py +6 -6
  290. ansible/modules/pip.py +21 -26
  291. ansible/modules/raw.py +6 -6
  292. ansible/modules/reboot.py +6 -6
  293. ansible/modules/replace.py +10 -14
  294. ansible/modules/rpm_key.py +7 -8
  295. ansible/modules/script.py +4 -4
  296. ansible/modules/service.py +10 -17
  297. ansible/modules/service_facts.py +87 -10
  298. ansible/modules/set_fact.py +5 -5
  299. ansible/modules/set_stats.py +4 -4
  300. ansible/modules/setup.py +2 -2
  301. ansible/modules/shell.py +6 -6
  302. ansible/modules/slurp.py +16 -19
  303. ansible/modules/stat.py +15 -31
  304. ansible/modules/subversion.py +15 -15
  305. ansible/modules/systemd.py +7 -7
  306. ansible/modules/systemd_service.py +7 -7
  307. ansible/modules/sysvinit.py +9 -9
  308. ansible/modules/tempfile.py +5 -6
  309. ansible/modules/template.py +6 -6
  310. ansible/modules/unarchive.py +38 -17
  311. ansible/modules/uri.py +33 -26
  312. ansible/modules/user.py +45 -32
  313. ansible/modules/validate_argument_spec.py +10 -7
  314. ansible/modules/wait_for.py +70 -60
  315. ansible/modules/wait_for_connection.py +6 -6
  316. ansible/modules/yum_repository.py +10 -9
  317. ansible/parsing/ajson.py +17 -37
  318. ansible/parsing/dataloader.py +99 -54
  319. ansible/parsing/mod_args.py +62 -60
  320. ansible/parsing/plugin_docs.py +21 -86
  321. ansible/parsing/quoting.py +1 -1
  322. ansible/parsing/splitter.py +27 -12
  323. ansible/parsing/utils/addresses.py +24 -24
  324. ansible/parsing/utils/jsonify.py +5 -1
  325. ansible/parsing/utils/yaml.py +32 -61
  326. ansible/parsing/vault/__init__.py +327 -99
  327. ansible/parsing/yaml/__init__.py +0 -18
  328. ansible/parsing/yaml/dumper.py +6 -120
  329. ansible/parsing/yaml/loader.py +6 -39
  330. ansible/parsing/yaml/objects.py +43 -335
  331. ansible/playbook/__init__.py +1 -1
  332. ansible/playbook/attribute.py +8 -3
  333. ansible/playbook/base.py +187 -134
  334. ansible/playbook/block.py +26 -24
  335. ansible/playbook/collectionsearch.py +1 -15
  336. ansible/playbook/conditional.py +3 -77
  337. ansible/playbook/handler.py +8 -2
  338. ansible/playbook/helpers.py +41 -53
  339. ansible/playbook/included_file.py +32 -26
  340. ansible/playbook/loop_control.py +2 -2
  341. ansible/playbook/play.py +85 -44
  342. ansible/playbook/play_context.py +14 -17
  343. ansible/playbook/playbook_include.py +27 -62
  344. ansible/playbook/role/__init__.py +64 -49
  345. ansible/playbook/role/definition.py +15 -17
  346. ansible/playbook/role/include.py +2 -4
  347. ansible/playbook/role/metadata.py +10 -11
  348. ansible/playbook/role_include.py +3 -3
  349. ansible/playbook/taggable.py +28 -12
  350. ansible/playbook/task.py +192 -121
  351. ansible/playbook/task_include.py +5 -5
  352. ansible/plugins/__init__.py +58 -26
  353. ansible/plugins/action/__init__.py +188 -186
  354. ansible/plugins/action/add_host.py +2 -2
  355. ansible/plugins/action/assemble.py +11 -18
  356. ansible/plugins/action/assert.py +55 -67
  357. ansible/plugins/action/async_status.py +7 -2
  358. ansible/plugins/action/copy.py +14 -17
  359. ansible/plugins/action/debug.py +37 -31
  360. ansible/plugins/action/dnf.py +3 -4
  361. ansible/plugins/action/fail.py +1 -1
  362. ansible/plugins/action/fetch.py +7 -8
  363. ansible/plugins/action/gather_facts.py +13 -14
  364. ansible/plugins/action/group_by.py +1 -1
  365. ansible/plugins/action/include_vars.py +10 -11
  366. ansible/plugins/action/package.py +8 -14
  367. ansible/plugins/action/pause.py +2 -2
  368. ansible/plugins/action/script.py +27 -38
  369. ansible/plugins/action/service.py +9 -18
  370. ansible/plugins/action/set_fact.py +3 -12
  371. ansible/plugins/action/set_stats.py +3 -8
  372. ansible/plugins/action/template.py +47 -67
  373. ansible/plugins/action/unarchive.py +6 -16
  374. ansible/plugins/action/uri.py +9 -20
  375. ansible/plugins/action/validate_argument_spec.py +5 -5
  376. ansible/plugins/action/wait_for_connection.py +1 -1
  377. ansible/plugins/become/__init__.py +31 -8
  378. ansible/plugins/become/runas.py +71 -0
  379. ansible/plugins/become/su.py +13 -8
  380. ansible/plugins/become/sudo.py +19 -0
  381. ansible/plugins/cache/__init__.py +52 -63
  382. ansible/plugins/cache/base.py +8 -0
  383. ansible/plugins/cache/jsonfile.py +10 -16
  384. ansible/plugins/cache/memory.py +6 -12
  385. ansible/plugins/callback/__init__.py +294 -201
  386. ansible/plugins/callback/default.py +99 -95
  387. ansible/plugins/callback/junit.py +44 -43
  388. ansible/plugins/callback/minimal.py +28 -25
  389. ansible/plugins/callback/oneline.py +34 -21
  390. ansible/plugins/callback/tree.py +27 -16
  391. ansible/plugins/connection/__init__.py +47 -34
  392. ansible/plugins/connection/local.py +156 -60
  393. ansible/plugins/connection/paramiko_ssh.py +34 -24
  394. ansible/plugins/connection/psrp.py +76 -165
  395. ansible/plugins/connection/ssh.py +326 -86
  396. ansible/plugins/connection/winrm.py +62 -141
  397. ansible/plugins/doc_fragments/action_common_attributes.py +14 -14
  398. ansible/plugins/doc_fragments/action_core.py +6 -6
  399. ansible/plugins/doc_fragments/backup.py +2 -2
  400. ansible/plugins/doc_fragments/checksum_common.py +27 -0
  401. ansible/plugins/doc_fragments/constructed.py +8 -4
  402. ansible/plugins/doc_fragments/decrypt.py +2 -2
  403. ansible/plugins/doc_fragments/default_callback.py +2 -2
  404. ansible/plugins/doc_fragments/files.py +2 -2
  405. ansible/plugins/doc_fragments/inventory_cache.py +2 -2
  406. ansible/plugins/doc_fragments/result_format_callback.py +2 -2
  407. ansible/plugins/doc_fragments/return_common.py +2 -2
  408. ansible/plugins/doc_fragments/template_common.py +4 -4
  409. ansible/plugins/doc_fragments/url.py +17 -1
  410. ansible/plugins/doc_fragments/url_windows.py +2 -2
  411. ansible/plugins/doc_fragments/validate.py +2 -2
  412. ansible/plugins/doc_fragments/vars_plugin_staging.py +2 -2
  413. ansible/plugins/filter/__init__.py +6 -2
  414. ansible/plugins/filter/b64decode.yml +22 -0
  415. ansible/plugins/filter/b64encode.yml +22 -0
  416. ansible/plugins/filter/bool.yml +11 -4
  417. ansible/plugins/filter/core.py +245 -120
  418. ansible/plugins/filter/encryption.py +42 -34
  419. ansible/plugins/filter/flatten.yml +3 -2
  420. ansible/plugins/filter/human_to_bytes.yml +1 -1
  421. ansible/plugins/filter/mathstuff.py +30 -37
  422. ansible/plugins/filter/password_hash.yml +8 -0
  423. ansible/plugins/filter/pow.yml +1 -1
  424. ansible/plugins/filter/regex_search.yml +1 -4
  425. ansible/plugins/filter/root.yml +1 -1
  426. ansible/plugins/filter/split.yml +1 -1
  427. ansible/plugins/filter/strftime.yml +3 -3
  428. ansible/plugins/filter/to_nice_yaml.yml +0 -4
  429. ansible/plugins/filter/to_uuid.yml +1 -1
  430. ansible/plugins/filter/to_yaml.yml +0 -4
  431. ansible/plugins/filter/unvault.yml +1 -1
  432. ansible/plugins/filter/urls.py +1 -1
  433. ansible/plugins/filter/urlsplit.py +8 -9
  434. ansible/plugins/filter/vault.yml +14 -9
  435. ansible/plugins/filter/win_basename.yml +6 -1
  436. ansible/plugins/filter/win_dirname.yml +5 -0
  437. ansible/plugins/inventory/__init__.py +107 -86
  438. ansible/plugins/inventory/advanced_host_list.py +7 -5
  439. ansible/plugins/inventory/auto.py +11 -4
  440. ansible/plugins/inventory/constructed.py +21 -24
  441. ansible/plugins/inventory/generator.py +16 -11
  442. ansible/plugins/inventory/host_list.py +7 -5
  443. ansible/plugins/inventory/ini.py +78 -44
  444. ansible/plugins/inventory/script.py +190 -120
  445. ansible/plugins/inventory/toml.py +16 -126
  446. ansible/plugins/inventory/yaml.py +10 -8
  447. ansible/plugins/list.py +72 -19
  448. ansible/plugins/loader.py +383 -198
  449. ansible/plugins/lookup/__init__.py +21 -4
  450. ansible/plugins/lookup/config.py +21 -35
  451. ansible/plugins/lookup/csvfile.py +19 -73
  452. ansible/plugins/lookup/dict.py +1 -6
  453. ansible/plugins/lookup/env.py +12 -9
  454. ansible/plugins/lookup/file.py +5 -8
  455. ansible/plugins/lookup/first_found.py +87 -55
  456. ansible/plugins/lookup/indexed_items.py +1 -10
  457. ansible/plugins/lookup/ini.py +14 -13
  458. ansible/plugins/lookup/items.py +1 -1
  459. ansible/plugins/lookup/lines.py +8 -1
  460. ansible/plugins/lookup/list.py +1 -1
  461. ansible/plugins/lookup/nested.py +2 -18
  462. ansible/plugins/lookup/password.py +5 -5
  463. ansible/plugins/lookup/pipe.py +5 -7
  464. ansible/plugins/lookup/sequence.py +18 -8
  465. ansible/plugins/lookup/subelements.py +1 -4
  466. ansible/plugins/lookup/template.py +47 -36
  467. ansible/plugins/lookup/together.py +0 -12
  468. ansible/plugins/lookup/unvault.py +1 -5
  469. ansible/plugins/lookup/url.py +4 -10
  470. ansible/plugins/lookup/vars.py +16 -24
  471. ansible/plugins/shell/__init__.py +58 -4
  472. ansible/plugins/shell/cmd.py +2 -2
  473. ansible/plugins/shell/powershell.py +106 -31
  474. ansible/plugins/shell/sh.py +13 -7
  475. ansible/plugins/strategy/__init__.py +168 -193
  476. ansible/plugins/strategy/debug.py +2 -2
  477. ansible/plugins/strategy/free.py +16 -31
  478. ansible/plugins/strategy/host_pinned.py +2 -2
  479. ansible/plugins/strategy/linear.py +41 -41
  480. ansible/plugins/terminal/__init__.py +4 -4
  481. ansible/plugins/test/__init__.py +7 -2
  482. ansible/plugins/test/core.py +75 -35
  483. ansible/plugins/test/files.py +1 -1
  484. ansible/plugins/test/finished.yml +1 -1
  485. ansible/plugins/test/mathstuff.py +3 -3
  486. ansible/plugins/test/uri.py +5 -8
  487. ansible/plugins/vars/host_group_vars.py +7 -14
  488. ansible/release.py +2 -2
  489. ansible/template/__init__.py +353 -943
  490. ansible/utils/__init__.py +0 -18
  491. ansible/utils/collection_loader/__init__.py +54 -5
  492. ansible/utils/collection_loader/_collection_config.py +5 -6
  493. ansible/utils/collection_loader/_collection_finder.py +82 -96
  494. ansible/utils/collection_loader/_collection_meta.py +15 -8
  495. ansible/utils/display.py +485 -73
  496. ansible/utils/encrypt.py +27 -19
  497. ansible/utils/fqcn.py +2 -2
  498. ansible/utils/galaxy.py +2 -2
  499. ansible/utils/hashing.py +8 -10
  500. ansible/utils/helpers.py +2 -2
  501. ansible/utils/listify.py +10 -8
  502. ansible/utils/lock.py +2 -2
  503. ansible/utils/path.py +10 -12
  504. ansible/utils/plugin_docs.py +16 -14
  505. ansible/utils/py3compat.py +2 -7
  506. ansible/utils/sentinel.py +4 -62
  507. ansible/utils/singleton.py +2 -0
  508. ansible/utils/ssh_functions.py +6 -2
  509. ansible/utils/unsafe_proxy.py +23 -332
  510. ansible/utils/vars.py +55 -8
  511. ansible/utils/version.py +2 -2
  512. ansible/vars/clean.py +5 -5
  513. ansible/vars/hostvars.py +60 -90
  514. ansible/vars/manager.py +220 -285
  515. ansible/vars/plugins.py +4 -4
  516. ansible/vars/reserved.py +13 -12
  517. {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/METADATA +4 -3
  518. ansible_core-2.19.0.dist-info/RECORD +1097 -0
  519. ansible_core-2.19.0.dist-info/licenses/licenses/BSD-3-Clause.txt +28 -0
  520. ansible_test/_data/completion/docker.txt +7 -7
  521. ansible_test/_data/completion/remote.txt +6 -6
  522. ansible_test/_data/completion/windows.txt +1 -0
  523. ansible_test/_data/requirements/ansible.txt +2 -2
  524. ansible_test/_data/requirements/sanity.ansible-doc.txt +3 -3
  525. ansible_test/_data/requirements/sanity.changelog.txt +2 -2
  526. ansible_test/_data/requirements/sanity.import.plugin.txt +2 -2
  527. ansible_test/_data/requirements/sanity.pep8.txt +1 -1
  528. ansible_test/_data/requirements/sanity.pylint.txt +5 -5
  529. ansible_test/_data/requirements/sanity.validate-modules.txt +2 -2
  530. ansible_test/_data/requirements/sanity.yamllint.txt +1 -1
  531. ansible_test/_data/requirements/units.txt +1 -0
  532. ansible_test/_internal/__init__.py +6 -0
  533. ansible_test/_internal/ansible_util.py +3 -1
  534. ansible_test/_internal/become.py +1 -0
  535. ansible_test/_internal/bootstrap.py +1 -0
  536. ansible_test/_internal/cache.py +1 -0
  537. ansible_test/_internal/cgroup.py +1 -0
  538. ansible_test/_internal/ci/__init__.py +1 -0
  539. ansible_test/_internal/ci/azp.py +1 -0
  540. ansible_test/_internal/ci/local.py +1 -0
  541. ansible_test/_internal/classification/__init__.py +1 -0
  542. ansible_test/_internal/classification/common.py +1 -0
  543. ansible_test/_internal/classification/csharp.py +1 -0
  544. ansible_test/_internal/classification/powershell.py +1 -0
  545. ansible_test/_internal/classification/python.py +1 -0
  546. ansible_test/_internal/cli/__init__.py +1 -0
  547. ansible_test/_internal/cli/actions.py +1 -0
  548. ansible_test/_internal/cli/argparsing/__init__.py +1 -0
  549. ansible_test/_internal/cli/argparsing/actions.py +1 -0
  550. ansible_test/_internal/cli/argparsing/argcompletion.py +1 -0
  551. ansible_test/_internal/cli/argparsing/parsers.py +1 -0
  552. ansible_test/_internal/cli/commands/__init__.py +11 -5
  553. ansible_test/_internal/cli/commands/coverage/__init__.py +1 -0
  554. ansible_test/_internal/cli/commands/coverage/analyze/__init__.py +1 -0
  555. ansible_test/_internal/cli/commands/coverage/analyze/targets/__init__.py +1 -0
  556. ansible_test/_internal/cli/commands/coverage/analyze/targets/combine.py +1 -0
  557. ansible_test/_internal/cli/commands/coverage/analyze/targets/expand.py +1 -0
  558. ansible_test/_internal/cli/commands/coverage/analyze/targets/filter.py +1 -0
  559. ansible_test/_internal/cli/commands/coverage/analyze/targets/generate.py +1 -0
  560. ansible_test/_internal/cli/commands/coverage/analyze/targets/missing.py +1 -0
  561. ansible_test/_internal/cli/commands/coverage/combine.py +1 -0
  562. ansible_test/_internal/cli/commands/coverage/erase.py +1 -0
  563. ansible_test/_internal/cli/commands/coverage/html.py +1 -0
  564. ansible_test/_internal/cli/commands/coverage/report.py +1 -0
  565. ansible_test/_internal/cli/commands/coverage/xml.py +1 -0
  566. ansible_test/_internal/cli/commands/env.py +1 -0
  567. ansible_test/_internal/cli/commands/integration/__init__.py +1 -0
  568. ansible_test/_internal/cli/commands/integration/network.py +1 -0
  569. ansible_test/_internal/cli/commands/integration/posix.py +1 -0
  570. ansible_test/_internal/cli/commands/integration/windows.py +1 -0
  571. ansible_test/_internal/cli/commands/sanity.py +9 -0
  572. ansible_test/_internal/cli/commands/shell.py +1 -0
  573. ansible_test/_internal/cli/commands/units.py +1 -0
  574. ansible_test/_internal/cli/compat.py +1 -0
  575. ansible_test/_internal/cli/completers.py +1 -0
  576. ansible_test/_internal/cli/converters.py +1 -0
  577. ansible_test/_internal/cli/environments.py +52 -5
  578. ansible_test/_internal/cli/epilog.py +1 -0
  579. ansible_test/_internal/cli/parsers/__init__.py +1 -0
  580. ansible_test/_internal/cli/parsers/base_argument_parsers.py +1 -0
  581. ansible_test/_internal/cli/parsers/helpers.py +1 -0
  582. ansible_test/_internal/cli/parsers/host_config_parsers.py +1 -0
  583. ansible_test/_internal/cli/parsers/key_value_parsers.py +1 -0
  584. ansible_test/_internal/cli/parsers/value_parsers.py +1 -0
  585. ansible_test/_internal/commands/__init__.py +1 -0
  586. ansible_test/_internal/commands/coverage/__init__.py +3 -2
  587. ansible_test/_internal/commands/coverage/analyze/__init__.py +1 -0
  588. ansible_test/_internal/commands/coverage/analyze/targets/__init__.py +1 -0
  589. ansible_test/_internal/commands/coverage/analyze/targets/combine.py +1 -0
  590. ansible_test/_internal/commands/coverage/analyze/targets/expand.py +1 -0
  591. ansible_test/_internal/commands/coverage/analyze/targets/filter.py +1 -0
  592. ansible_test/_internal/commands/coverage/analyze/targets/generate.py +1 -0
  593. ansible_test/_internal/commands/coverage/analyze/targets/missing.py +1 -0
  594. ansible_test/_internal/commands/coverage/combine.py +2 -1
  595. ansible_test/_internal/commands/coverage/erase.py +1 -0
  596. ansible_test/_internal/commands/coverage/html.py +1 -0
  597. ansible_test/_internal/commands/coverage/report.py +1 -0
  598. ansible_test/_internal/commands/coverage/xml.py +1 -0
  599. ansible_test/_internal/commands/env/__init__.py +2 -0
  600. ansible_test/_internal/commands/integration/__init__.py +22 -5
  601. ansible_test/_internal/commands/integration/cloud/__init__.py +1 -0
  602. ansible_test/_internal/commands/integration/cloud/acme.py +2 -1
  603. ansible_test/_internal/commands/integration/cloud/aws.py +1 -0
  604. ansible_test/_internal/commands/integration/cloud/azure.py +1 -0
  605. ansible_test/_internal/commands/integration/cloud/cs.py +1 -0
  606. ansible_test/_internal/commands/integration/cloud/digitalocean.py +1 -0
  607. ansible_test/_internal/commands/integration/cloud/galaxy.py +3 -2
  608. ansible_test/_internal/commands/integration/cloud/hcloud.py +1 -0
  609. ansible_test/_internal/commands/integration/cloud/httptester.py +3 -2
  610. ansible_test/_internal/commands/integration/cloud/nios.py +2 -1
  611. ansible_test/_internal/commands/integration/cloud/opennebula.py +1 -0
  612. ansible_test/_internal/commands/integration/cloud/openshift.py +1 -0
  613. ansible_test/_internal/commands/integration/cloud/scaleway.py +1 -0
  614. ansible_test/_internal/commands/integration/cloud/vcenter.py +1 -0
  615. ansible_test/_internal/commands/integration/cloud/vultr.py +1 -0
  616. ansible_test/_internal/commands/integration/coverage.py +8 -2
  617. ansible_test/_internal/commands/integration/filters.py +1 -0
  618. ansible_test/_internal/commands/integration/network.py +1 -0
  619. ansible_test/_internal/commands/integration/posix.py +1 -0
  620. ansible_test/_internal/commands/integration/windows.py +1 -0
  621. ansible_test/_internal/commands/sanity/__init__.py +19 -2
  622. ansible_test/_internal/commands/sanity/ansible_doc.py +1 -0
  623. ansible_test/_internal/commands/sanity/bin_symlinks.py +1 -0
  624. ansible_test/_internal/commands/sanity/compile.py +1 -0
  625. ansible_test/_internal/commands/sanity/ignores.py +1 -0
  626. ansible_test/_internal/commands/sanity/import.py +1 -0
  627. ansible_test/_internal/commands/sanity/integration_aliases.py +12 -0
  628. ansible_test/_internal/commands/sanity/pep8.py +1 -0
  629. ansible_test/_internal/commands/sanity/pslint.py +1 -0
  630. ansible_test/_internal/commands/sanity/pylint.py +25 -26
  631. ansible_test/_internal/commands/sanity/shellcheck.py +1 -0
  632. ansible_test/_internal/commands/sanity/validate_modules.py +1 -0
  633. ansible_test/_internal/commands/sanity/yamllint.py +1 -0
  634. ansible_test/_internal/commands/shell/__init__.py +44 -4
  635. ansible_test/_internal/commands/units/__init__.py +5 -1
  636. ansible_test/_internal/compat/__init__.py +1 -0
  637. ansible_test/_internal/compat/packaging.py +1 -0
  638. ansible_test/_internal/compat/yaml.py +1 -0
  639. ansible_test/_internal/completion.py +1 -0
  640. ansible_test/_internal/config.py +23 -13
  641. ansible_test/_internal/connections.py +1 -0
  642. ansible_test/_internal/constants.py +1 -0
  643. ansible_test/_internal/containers.py +1 -0
  644. ansible_test/_internal/content_config.py +1 -0
  645. ansible_test/_internal/core_ci.py +1 -0
  646. ansible_test/_internal/coverage_util.py +11 -10
  647. ansible_test/_internal/data.py +1 -0
  648. ansible_test/_internal/debugging.py +166 -0
  649. ansible_test/_internal/delegation.py +22 -13
  650. ansible_test/_internal/dev/__init__.py +1 -0
  651. ansible_test/_internal/dev/container_probe.py +1 -0
  652. ansible_test/_internal/diff.py +3 -2
  653. ansible_test/_internal/docker_util.py +2 -1
  654. ansible_test/_internal/encoding.py +1 -0
  655. ansible_test/_internal/executor.py +1 -0
  656. ansible_test/_internal/git.py +1 -0
  657. ansible_test/_internal/host_configs.py +1 -0
  658. ansible_test/_internal/host_profiles.py +260 -16
  659. ansible_test/_internal/http.py +1 -0
  660. ansible_test/_internal/init.py +1 -0
  661. ansible_test/_internal/inventory.py +39 -3
  662. ansible_test/_internal/io.py +1 -0
  663. ansible_test/_internal/metadata.py +95 -4
  664. ansible_test/_internal/payload.py +1 -0
  665. ansible_test/_internal/processes.py +80 -0
  666. ansible_test/_internal/provider/__init__.py +1 -0
  667. ansible_test/_internal/provider/layout/__init__.py +1 -0
  668. ansible_test/_internal/provider/layout/ansible.py +1 -0
  669. ansible_test/_internal/provider/layout/collection.py +1 -0
  670. ansible_test/_internal/provider/layout/unsupported.py +1 -0
  671. ansible_test/_internal/provider/source/__init__.py +1 -0
  672. ansible_test/_internal/provider/source/git.py +1 -0
  673. ansible_test/_internal/provider/source/installed.py +1 -0
  674. ansible_test/_internal/provider/source/unsupported.py +1 -0
  675. ansible_test/_internal/provider/source/unversioned.py +1 -0
  676. ansible_test/_internal/provisioning.py +11 -4
  677. ansible_test/_internal/pypi_proxy.py +6 -5
  678. ansible_test/_internal/python_requirements.py +28 -0
  679. ansible_test/_internal/ssh.py +2 -5
  680. ansible_test/_internal/target.py +9 -0
  681. ansible_test/_internal/test.py +3 -2
  682. ansible_test/_internal/thread.py +3 -1
  683. ansible_test/_internal/timeout.py +2 -1
  684. ansible_test/_internal/util.py +41 -12
  685. ansible_test/_internal/util_common.py +18 -5
  686. ansible_test/_internal/venv.py +1 -0
  687. ansible_test/_util/controller/sanity/code-smell/action-plugin-docs.py +1 -0
  688. ansible_test/_util/controller/sanity/code-smell/changelog/sphinx.py +1 -0
  689. ansible_test/_util/controller/sanity/code-smell/changelog.py +1 -0
  690. ansible_test/_util/controller/sanity/code-smell/empty-init.py +1 -0
  691. ansible_test/_util/controller/sanity/code-smell/line-endings.py +1 -0
  692. ansible_test/_util/controller/sanity/code-smell/no-assert.py +1 -0
  693. ansible_test/_util/controller/sanity/code-smell/no-get-exception.py +1 -0
  694. ansible_test/_util/controller/sanity/code-smell/no-illegal-filenames.py +1 -0
  695. ansible_test/_util/controller/sanity/code-smell/no-smart-quotes.py +1 -0
  696. ansible_test/_util/controller/sanity/code-smell/replace-urlopen.py +1 -0
  697. ansible_test/_util/controller/sanity/code-smell/runtime-metadata.py +28 -1
  698. ansible_test/_util/controller/sanity/code-smell/shebang.py +1 -0
  699. ansible_test/_util/controller/sanity/code-smell/symlinks.py +1 -0
  700. ansible_test/_util/controller/sanity/code-smell/use-argspec-type-path.py +1 -0
  701. ansible_test/_util/controller/sanity/code-smell/use-compat-six.py +1 -0
  702. ansible_test/_util/controller/sanity/integration-aliases/yaml_to_json.py +2 -1
  703. ansible_test/_util/controller/sanity/pep8/current-ignore.txt +4 -0
  704. ansible_test/_util/controller/sanity/pylint/config/ansible-test-target.cfg +8 -5
  705. ansible_test/_util/controller/sanity/pylint/config/ansible-test.cfg +8 -5
  706. ansible_test/_util/controller/sanity/pylint/config/code-smell.cfg +8 -5
  707. ansible_test/_util/controller/sanity/pylint/config/collection.cfg +4 -5
  708. ansible_test/_util/controller/sanity/pylint/config/default.cfg +8 -7
  709. ansible_test/_util/controller/sanity/pylint/plugins/deprecated_calls.py +541 -0
  710. ansible_test/_util/controller/sanity/pylint/plugins/deprecated_comment.py +137 -0
  711. ansible_test/_util/controller/sanity/pylint/plugins/hide_unraisable.py +1 -0
  712. ansible_test/_util/controller/sanity/pylint/plugins/string_format.py +1 -8
  713. ansible_test/_util/controller/sanity/pylint/plugins/unwanted.py +1 -8
  714. ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py +55 -28
  715. ansible_test/_util/controller/sanity/validate-modules/validate_modules/module_args.py +12 -5
  716. ansible_test/_util/controller/sanity/validate-modules/validate_modules/schema.py +13 -2
  717. ansible_test/_util/controller/sanity/validate-modules/validate_modules/utils.py +1 -0
  718. ansible_test/_util/controller/sanity/yamllint/yamllinter.py +35 -17
  719. ansible_test/_util/controller/tools/collection_detail.py +1 -0
  720. ansible_test/_util/controller/tools/yaml_to_json.py +2 -1
  721. ansible_test/_util/target/injector/python.py +8 -0
  722. ansible_test/_util/target/pytest/plugins/ansible_forked.py +6 -1
  723. ansible_test/_util/target/pytest/plugins/ansible_pytest_collections.py +2 -1
  724. ansible_test/_util/target/pytest/plugins/ansible_pytest_coverage.py +1 -0
  725. ansible_test/_util/target/sanity/compile/compile.py +1 -0
  726. ansible_test/_util/target/sanity/import/importer.py +15 -16
  727. ansible_test/_util/target/setup/bootstrap.sh +9 -20
  728. ansible_test/_util/target/setup/probe_cgroups.py +1 -0
  729. ansible_test/_util/target/setup/quiet_pip.py +1 -0
  730. ansible_test/_util/target/setup/requirements.py +38 -36
  731. ansible_test/_util/target/tools/virtualenvcheck.py +2 -1
  732. ansible_test/_util/target/tools/yamlcheck.py +2 -1
  733. ansible/compat/selectors.py +0 -32
  734. ansible/errors/yaml_strings.py +0 -138
  735. ansible/executor/action_write_locks.py +0 -44
  736. ansible/executor/discovery/python_target.py +0 -47
  737. ansible/executor/powershell/module_powershell_wrapper.ps1 +0 -86
  738. ansible/executor/powershell/module_script_wrapper.ps1 +0 -22
  739. ansible/module_utils/compat/importlib.py +0 -26
  740. ansible/module_utils/compat/selectors.py +0 -32
  741. ansible/module_utils/pycompat24.py +0 -73
  742. ansible/parsing/yaml/constructor.py +0 -178
  743. ansible/template/native_helpers.py +0 -251
  744. ansible/template/template.py +0 -43
  745. ansible/template/vars.py +0 -77
  746. ansible/utils/native_jinja.py +0 -11
  747. ansible/vars/fact_cache.py +0 -71
  748. ansible_core-2.18.7rc1.dist-info/RECORD +0 -992
  749. ansible_test/_util/controller/sanity/pylint/plugins/deprecated.py +0 -411
  750. {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/WHEEL +0 -0
  751. {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/entry_points.txt +0 -0
  752. {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/COPYING +0 -0
  753. {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/Apache-License.txt +0 -0
  754. {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/MIT-license.txt +0 -0
  755. {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/PSF-license.txt +0 -0
  756. {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/simplified_bsd.txt +0 -0
  757. {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/top_level.txt +0 -0
@@ -17,8 +17,8 @@
17
17
 
18
18
  from __future__ import annotations
19
19
 
20
- import errno
21
20
  import fcntl
21
+ import functools
22
22
  import os
23
23
  import random
24
24
  import shlex
@@ -27,11 +27,18 @@ import subprocess
27
27
  import sys
28
28
  import tempfile
29
29
  import warnings
30
+ import typing as t
30
31
 
31
32
  from binascii import hexlify
32
33
  from binascii import unhexlify
33
34
  from binascii import Error as BinasciiError
34
35
 
36
+ from ansible.module_utils._internal._datatag import (
37
+ AnsibleTagHelper, AnsibleTaggedObject, _AnsibleTagsMapping, _EmptyROInternalTagsMapping, _EMPTY_INTERNAL_TAGS_MAPPING,
38
+ )
39
+ from ansible._internal._templating import _jinja_common
40
+ from ansible._internal._datatag._tags import Origin, VaultedValue, TrustedAsTemplate
41
+
35
42
  HAS_CRYPTOGRAPHY = False
36
43
  CRYPTOGRAPHY_BACKEND = None
37
44
  try:
@@ -141,11 +148,13 @@ def _parse_vaulttext_envelope(b_vaulttext_envelope, default_vault_id=None):
141
148
  vault_id = to_text(b_tmpheader[3].strip())
142
149
 
143
150
  b_ciphertext = b''.join(b_tmpdata[1:])
151
+ # DTFIX7: possible candidate for propagate_origin
152
+ b_ciphertext = AnsibleTagHelper.tag_copy(b_vaulttext_envelope, b_ciphertext)
144
153
 
145
154
  return b_ciphertext, b_version, cipher_name, vault_id
146
155
 
147
156
 
148
- def parse_vaulttext_envelope(b_vaulttext_envelope, default_vault_id=None, filename=None):
157
+ def parse_vaulttext_envelope(b_vaulttext_envelope, default_vault_id=None):
149
158
  """Parse the vaulttext envelope
150
159
 
151
160
  When data is saved, it has a header prepended and is formatted into 80
@@ -153,11 +162,8 @@ def parse_vaulttext_envelope(b_vaulttext_envelope, default_vault_id=None, filena
153
162
  and then removes the header and the inserted newlines. The string returned
154
163
  is suitable for processing by the Cipher classes.
155
164
 
156
- :arg b_vaulttext: byte str containing the data from a save file
157
- :kwarg default_vault_id: The vault_id name to use if the vaulttext does not provide one.
158
- :kwarg filename: The filename that the data came from. This is only
159
- used to make better error messages in case the data cannot be
160
- decrypted. This is optional.
165
+ :arg b_vaulttext_envelope: byte str containing the data from a save file
166
+ :arg default_vault_id: The vault_id name to use if the vaulttext does not provide one.
161
167
  :returns: A tuple of byte str of the vaulttext suitable to pass to parse_vaultext,
162
168
  a byte str of the vault format version,
163
169
  the name of the cipher used, and the vault_id.
@@ -168,12 +174,8 @@ def parse_vaulttext_envelope(b_vaulttext_envelope, default_vault_id=None, filena
168
174
 
169
175
  try:
170
176
  return _parse_vaulttext_envelope(b_vaulttext_envelope, default_vault_id)
171
- except Exception as exc:
172
- msg = "Vault envelope format error"
173
- if filename:
174
- msg += ' in %s' % (filename)
175
- msg += ': %s' % exc
176
- raise AnsibleVaultFormatError(msg)
177
+ except Exception as ex:
178
+ raise AnsibleVaultFormatError("Vault envelope format error.", obj=b_vaulttext_envelope) from ex
177
179
 
178
180
 
179
181
  def format_vaulttext_envelope(b_ciphertext, cipher_name, version=None, vault_id=None):
@@ -219,9 +221,10 @@ def format_vaulttext_envelope(b_ciphertext, cipher_name, version=None, vault_id=
219
221
 
220
222
  def _unhexlify(b_data):
221
223
  try:
222
- return unhexlify(b_data)
223
- except (BinasciiError, TypeError) as exc:
224
- raise AnsibleVaultFormatError('Vault format unhexlify error: %s' % exc)
224
+ # DTFIX7: possible candidate for propagate_origin
225
+ return AnsibleTagHelper.tag_copy(b_data, unhexlify(b_data))
226
+ except (BinasciiError, TypeError) as ex:
227
+ raise AnsibleVaultFormatError('Vault format unhexlify error.', obj=b_data) from ex
225
228
 
226
229
 
227
230
  def _parse_vaulttext(b_vaulttext):
@@ -247,25 +250,24 @@ def parse_vaulttext(b_vaulttext):
247
250
  return _parse_vaulttext(b_vaulttext)
248
251
  except AnsibleVaultFormatError:
249
252
  raise
250
- except Exception as exc:
251
- msg = "Vault vaulttext format error: %s" % exc
252
- raise AnsibleVaultFormatError(msg)
253
+ except Exception as ex:
254
+ raise AnsibleVaultFormatError("Vault vaulttext format error.", obj=b_vaulttext) from ex
253
255
 
254
256
 
255
257
  def verify_secret_is_not_empty(secret, msg=None):
256
- '''Check the secret against minimal requirements.
258
+ """Check the secret against minimal requirements.
257
259
 
258
260
  Raises: AnsibleVaultPasswordError if the password does not meet requirements.
259
261
 
260
262
  Currently, only requirement is that the password is not None or an empty string.
261
- '''
263
+ """
262
264
  msg = msg or 'Invalid vault password was provided'
263
265
  if not secret:
264
266
  raise AnsibleVaultPasswordError(msg)
265
267
 
266
268
 
267
269
  class VaultSecret:
268
- '''Opaque/abstract objects for a single vault secret. ie, a password or a key.'''
270
+ """Opaque/abstract objects for a single vault secret. ie, a password or a key."""
269
271
 
270
272
  def __init__(self, _bytes=None):
271
273
  # FIXME: ? that seems wrong... Unset etc?
@@ -273,10 +275,10 @@ class VaultSecret:
273
275
 
274
276
  @property
275
277
  def bytes(self):
276
- '''The secret as a bytestring.
278
+ """The secret as a bytestring.
277
279
 
278
280
  Sub classes that store text types will need to override to encode the text to bytes.
279
- '''
281
+ """
280
282
  return self._bytes
281
283
 
282
284
  def load(self):
@@ -335,7 +337,7 @@ class PromptVaultSecret(VaultSecret):
335
337
 
336
338
 
337
339
  def script_is_client(filename):
338
- '''Determine if a vault secret script is a client script that can be given --vault-id args'''
340
+ """Determine if a vault secret script is a client script that can be given --vault-id args"""
339
341
 
340
342
  # if password script is 'something-client' or 'something-client.[sh|py|rb|etc]'
341
343
  # script_name can still have '.' or could be entire filename if there is no ext
@@ -349,7 +351,7 @@ def script_is_client(filename):
349
351
 
350
352
 
351
353
  def get_file_vault_secret(filename=None, vault_id=None, encoding=None, loader=None):
352
- ''' Get secret from file content or execute file and get secret from stdout '''
354
+ """ Get secret from file content or execute file and get secret from stdout """
353
355
 
354
356
  # we unfrack but not follow the full path/context to possible vault script
355
357
  # so when the script uses 'adjacent' file for configuration or similar
@@ -411,10 +413,10 @@ class FileVaultSecret(VaultSecret):
411
413
  try:
412
414
  with open(filename, "rb") as f:
413
415
  vault_pass = f.read().strip()
414
- except (OSError, IOError) as e:
415
- raise AnsibleError("Could not read vault password file %s: %s" % (filename, e))
416
+ except OSError as ex:
417
+ raise AnsibleError(f"Could not read vault password file {filename!r}.") from ex
416
418
 
417
- b_vault_data, dummy = self.loader._decrypt_if_vault_data(vault_pass, filename)
419
+ b_vault_data, dummy = self.loader._decrypt_if_vault_data(vault_pass)
418
420
 
419
421
  vault_pass = b_vault_data.strip(b'\r\n')
420
422
 
@@ -519,7 +521,7 @@ class ClientScriptVaultSecret(ScriptVaultSecret):
519
521
 
520
522
 
521
523
  def match_secrets(secrets, target_vault_ids):
522
- '''Find all VaultSecret objects that are mapped to any of the target_vault_ids in secrets'''
524
+ """Find all VaultSecret objects that are mapped to any of the target_vault_ids in secrets"""
523
525
  if not secrets:
524
526
  return []
525
527
 
@@ -528,10 +530,10 @@ def match_secrets(secrets, target_vault_ids):
528
530
 
529
531
 
530
532
  def match_best_secret(secrets, target_vault_ids):
531
- '''Find the best secret from secrets that matches target_vault_ids
533
+ """Find the best secret from secrets that matches target_vault_ids
532
534
 
533
535
  Since secrets should be ordered so the early secrets are 'better' than later ones, this
534
- just finds all the matches, then returns the first secret'''
536
+ just finds all the matches, then returns the first secret"""
535
537
  matches = match_secrets(secrets, target_vault_ids)
536
538
  if matches:
537
539
  return matches[0]
@@ -560,7 +562,7 @@ def match_encrypt_vault_id_secret(secrets, encrypt_vault_id=None):
560
562
 
561
563
 
562
564
  def match_encrypt_secret(secrets, encrypt_vault_id=None):
563
- '''Find the best/first/only secret in secrets to use for encrypting'''
565
+ """Find the best/first/only secret in secrets to use for encrypting"""
564
566
 
565
567
  display.vvvv(u'encrypt_vault_id=%s' % to_text(encrypt_vault_id))
566
568
  # See if the --encrypt-vault-id matches a vault-id
@@ -568,8 +570,8 @@ def match_encrypt_secret(secrets, encrypt_vault_id=None):
568
570
  return match_encrypt_vault_id_secret(secrets,
569
571
  encrypt_vault_id=encrypt_vault_id)
570
572
 
571
- # Find the best/first secret from secrets since we didnt specify otherwise
572
- # ie, consider all of the available secrets as matches
573
+ # Find the best/first secret from secrets since we didn't specify otherwise
574
+ # ie, consider all the available secrets as matches
573
575
  _vault_id_matchers = [_vault_id for _vault_id, dummy in secrets]
574
576
  best_secret = match_best_secret(secrets, _vault_id_matchers)
575
577
 
@@ -633,58 +635,44 @@ class VaultLib:
633
635
  vault_id=vault_id)
634
636
  return b_vaulttext
635
637
 
636
- def decrypt(self, vaulttext, filename=None, obj=None):
637
- '''Decrypt a piece of vault encrypted data.
638
+ def decrypt(self, vaulttext):
639
+ """Decrypt a piece of vault encrypted data.
638
640
 
639
641
  :arg vaulttext: a string to decrypt. Since vault encrypted data is an
640
642
  ascii text format this can be either a byte str or unicode string.
641
- :kwarg filename: a filename that the data came from. This is only
642
- used to make better error messages in case the data cannot be
643
- decrypted.
644
- :returns: a byte string containing the decrypted data and the vault-id that was used
645
-
646
- '''
647
- plaintext, vault_id, vault_secret = self.decrypt_and_get_vault_id(vaulttext, filename=filename, obj=obj)
643
+ :returns: a byte string containing the decrypted data
644
+ """
645
+ plaintext, vault_id, vault_secret = self.decrypt_and_get_vault_id(vaulttext)
648
646
  return plaintext
649
647
 
650
- def decrypt_and_get_vault_id(self, vaulttext, filename=None, obj=None):
648
+ def decrypt_and_get_vault_id(self, vaulttext):
651
649
  """Decrypt a piece of vault encrypted data.
652
650
 
653
651
  :arg vaulttext: a string to decrypt. Since vault encrypted data is an
654
652
  ascii text format this can be either a byte str or unicode string.
655
- :kwarg filename: a filename that the data came from. This is only
656
- used to make better error messages in case the data cannot be
657
- decrypted.
658
653
  :returns: a byte string containing the decrypted data and the vault-id vault-secret that was used
659
-
660
654
  """
661
- b_vaulttext = to_bytes(vaulttext, errors='strict', encoding='utf-8')
655
+ origin = Origin.get_tag(vaulttext)
656
+
657
+ b_vaulttext = to_bytes(vaulttext, nonstring='error') # enforce vaulttext is str/bytes, keep type check if removing type conversion
662
658
 
663
659
  if self.secrets is None:
664
- msg = "A vault password must be specified to decrypt data"
665
- if filename:
666
- msg += " in file %s" % to_native(filename)
667
- raise AnsibleVaultError(msg)
660
+ raise AnsibleVaultError("A vault password must be specified to decrypt data.", obj=vaulttext)
668
661
 
669
662
  if not is_encrypted(b_vaulttext):
670
- msg = "input is not vault encrypted data. "
671
- if filename:
672
- msg += "%s is not a vault encrypted file" % to_native(filename)
673
- raise AnsibleError(msg)
663
+ raise AnsibleVaultError("Input is not vault encrypted data.", obj=vaulttext)
674
664
 
675
- b_vaulttext, dummy, cipher_name, vault_id = parse_vaulttext_envelope(b_vaulttext, filename=filename)
665
+ b_vaulttext, dummy, cipher_name, vault_id = parse_vaulttext_envelope(b_vaulttext)
676
666
 
677
667
  # create the cipher object, note that the cipher used for decrypt can
678
668
  # be different than the cipher used for encrypt
679
669
  if cipher_name in CIPHER_ALLOWLIST:
680
670
  this_cipher = CIPHER_MAPPING[cipher_name]()
681
671
  else:
682
- raise AnsibleError("{0} cipher could not be found".format(cipher_name))
683
-
684
- b_plaintext = None
672
+ raise AnsibleVaultError(f"Cipher {cipher_name!r} could not be found.", obj=vaulttext)
685
673
 
686
674
  if not self.secrets:
687
- raise AnsibleVaultError('Attempting to decrypt but no vault secrets found')
675
+ raise AnsibleVaultError('Attempting to decrypt but no vault secrets found.', obj=vaulttext)
688
676
 
689
677
  # WARNING: Currently, the vault id is not required to match the vault id in the vault blob to
690
678
  # decrypt a vault properly. The vault id in the vault blob is not part of the encrypted
@@ -697,15 +685,13 @@ class VaultLib:
697
685
  # we check it first.
698
686
 
699
687
  vault_id_matchers = []
700
- vault_id_used = None
701
- vault_secret_used = None
702
688
 
703
689
  if vault_id:
704
690
  display.vvvvv(u'Found a vault_id (%s) in the vaulttext' % to_text(vault_id))
705
691
  vault_id_matchers.append(vault_id)
706
692
  _matches = match_secrets(self.secrets, vault_id_matchers)
707
693
  if _matches:
708
- display.vvvvv(u'We have a secret associated with vault id (%s), will try to use to decrypt %s' % (to_text(vault_id), to_text(filename)))
694
+ display.vvvvv(u'We have a secret associated with vault id (%s), will try to use to decrypt %s' % (to_text(vault_id), to_text(origin)))
709
695
  else:
710
696
  display.vvvvv(u'Found a vault_id (%s) in the vault text, but we do not have a associated secret (--vault-id)' % to_text(vault_id))
711
697
 
@@ -719,45 +705,32 @@ class VaultLib:
719
705
 
720
706
  # for vault_secret_id in vault_secret_ids:
721
707
  for vault_secret_id, vault_secret in matched_secrets:
722
- display.vvvvv(u'Trying to use vault secret=(%s) id=%s to decrypt %s' % (to_text(vault_secret), to_text(vault_secret_id), to_text(filename)))
708
+ display.vvvvv(u'Trying to use vault secret=(%s) id=%s to decrypt %s' % (to_text(vault_secret), to_text(vault_secret_id), to_text(origin)))
723
709
 
724
710
  try:
725
711
  # secret = self.secrets[vault_secret_id]
726
712
  display.vvvv(u'Trying secret %s for vault_id=%s' % (to_text(vault_secret), to_text(vault_secret_id)))
727
713
  b_plaintext = this_cipher.decrypt(b_vaulttext, vault_secret)
714
+ # DTFIX7: possible candidate for propagate_origin
715
+ b_plaintext = AnsibleTagHelper.tag_copy(vaulttext, b_plaintext)
728
716
  if b_plaintext is not None:
729
717
  vault_id_used = vault_secret_id
730
718
  vault_secret_used = vault_secret
731
719
  file_slug = ''
732
- if filename:
733
- file_slug = ' of "%s"' % filename
720
+ if origin:
721
+ file_slug = ' of "%s"' % origin
734
722
  display.vvvvv(
735
723
  u'Decrypt%s successful with secret=%s and vault_id=%s' % (to_text(file_slug), to_text(vault_secret), to_text(vault_secret_id))
736
724
  )
737
725
  break
738
- except AnsibleVaultFormatError as exc:
739
- exc.obj = obj
740
- msg = u"There was a vault format error"
741
- if filename:
742
- msg += u' in %s' % (to_text(filename))
743
- msg += u': %s' % to_text(exc)
744
- display.warning(msg, formatted=True)
726
+ except AnsibleVaultFormatError:
745
727
  raise
746
728
  except AnsibleError as e:
747
729
  display.vvvv(u'Tried to use the vault secret (%s) to decrypt (%s) but it failed. Error: %s' %
748
- (to_text(vault_secret_id), to_text(filename), e))
730
+ (to_text(vault_secret_id), to_text(origin), e))
749
731
  continue
750
732
  else:
751
- msg = "Decryption failed (no vault secrets were found that could decrypt)"
752
- if filename:
753
- msg += " on %s" % to_native(filename)
754
- raise AnsibleVaultError(msg)
755
-
756
- if b_plaintext is None:
757
- msg = "Decryption failed"
758
- if filename:
759
- msg += " on %s" % to_native(filename)
760
- raise AnsibleError(msg)
733
+ raise AnsibleVaultError("Decryption failed (no vault secrets were found that could decrypt).", obj=vaulttext)
761
734
 
762
735
  return b_plaintext, vault_id_used, vault_secret_used
763
736
 
@@ -916,7 +889,7 @@ class VaultEditor:
916
889
  ciphertext = self.read_data(filename)
917
890
 
918
891
  try:
919
- plaintext = self.vault.decrypt(ciphertext, filename=filename)
892
+ plaintext = self.vault.decrypt(ciphertext)
920
893
  except AnsibleError as e:
921
894
  raise AnsibleError("%s for %s" % (to_native(e), to_native(filename)))
922
895
  self.write_data(plaintext, output_file or filename, shred=False)
@@ -956,7 +929,7 @@ class VaultEditor:
956
929
 
957
930
  # Figure out the vault id from the file, to select the right secret to re-encrypt it
958
931
  # (duplicates parts of decrypt, but alas...)
959
- dummy, dummy, cipher_name, vault_id = parse_vaulttext_envelope(b_vaulttext, filename=filename)
932
+ dummy, dummy, cipher_name, vault_id = parse_vaulttext_envelope(b_vaulttext)
960
933
 
961
934
  # vault id here may not be the vault id actually used for decrypting
962
935
  # as when the edited file has no vault-id but is decrypted by non-default id in secrets
@@ -974,7 +947,7 @@ class VaultEditor:
974
947
  vaulttext = to_text(b_vaulttext)
975
948
 
976
949
  try:
977
- plaintext = self.vault.decrypt(vaulttext, filename=filename)
950
+ plaintext = self.vault.decrypt(vaulttext)
978
951
  return plaintext
979
952
  except AnsibleError as e:
980
953
  raise AnsibleVaultError("%s for %s" % (to_native(e), to_native(filename)))
@@ -1024,10 +997,12 @@ class VaultEditor:
1024
997
 
1025
998
  try:
1026
999
  if filename == '-':
1027
- data = sys.stdin.buffer.read()
1000
+ data = Origin(description='<stdin>').tag(sys.stdin.buffer.read())
1028
1001
  else:
1002
+ filename = os.path.abspath(filename)
1003
+
1029
1004
  with open(filename, "rb") as fh:
1030
- data = fh.read()
1005
+ data = Origin(path=filename).tag(fh.read())
1031
1006
  except Exception as e:
1032
1007
  msg = to_native(e)
1033
1008
  if not msg:
@@ -1095,13 +1070,10 @@ class VaultEditor:
1095
1070
  try:
1096
1071
  # create file with secure permissions
1097
1072
  fd = os.open(thefile, os.O_CREAT | os.O_EXCL | os.O_RDWR | os.O_TRUNC, mode)
1098
- except OSError as ose:
1099
- # Want to catch FileExistsError, which doesn't exist in Python 2, so catch OSError
1100
- # and compare the error number to get equivalent behavior in Python 2/3
1101
- if ose.errno == errno.EEXIST:
1102
- raise AnsibleError('Vault file got recreated while we were operating on it: %s' % to_native(ose))
1103
-
1104
- raise AnsibleError('Problem creating temporary vault file: %s' % to_native(ose))
1073
+ except FileExistsError as ex:
1074
+ raise AnsibleError('Vault file got recreated while we were operating on it.') from ex
1075
+ except OSError as ex:
1076
+ raise AnsibleError('Problem creating temporary vault file.') from ex
1105
1077
 
1106
1078
  try:
1107
1079
  # now write to the file and ensure ours is only data in it
@@ -1170,6 +1142,7 @@ class VaultAES256:
1170
1142
  return b_derivedkey
1171
1143
 
1172
1144
  @classmethod
1145
+ @functools.cache # Concurrent first-use by multiple threads will all execute the method body.
1173
1146
  def _gen_key_initctr(cls, b_password, b_salt):
1174
1147
  # 16 for AES 128, 32 for AES256
1175
1148
  key_length = 32
@@ -1302,3 +1275,258 @@ class VaultAES256:
1302
1275
  CIPHER_MAPPING = {
1303
1276
  u'AES256': VaultAES256,
1304
1277
  }
1278
+
1279
+
1280
+ class VaultSecretsContext:
1281
+ """Provides context-style access to vault secrets."""
1282
+ _current: t.ClassVar[t.Self | None] = None
1283
+
1284
+ def __init__(self, secrets: list[tuple[str, VaultSecret]]) -> None:
1285
+ self.secrets = secrets
1286
+
1287
+ @classmethod
1288
+ def initialize(cls, value: t.Self) -> None:
1289
+ """
1290
+ Initialize VaultSecretsContext with the specified instance and secrets (since it's not a lazy or per-thread context).
1291
+ This method will fail if called more than once.
1292
+ """
1293
+ if cls._current:
1294
+ raise RuntimeError(f"The {cls.__name__} context is already initialized.")
1295
+
1296
+ cls._current = value
1297
+
1298
+ @classmethod
1299
+ def current(cls, optional: bool = False) -> t.Self:
1300
+ """Access vault secrets, if initialized, ala `AmbientContextBase.current()`."""
1301
+ if not cls._current and not optional:
1302
+ raise ReferenceError(f"A required {cls.__name__} context is not active.")
1303
+
1304
+ return cls._current
1305
+
1306
+
1307
+ @t.final
1308
+ class EncryptedString(AnsibleTaggedObject):
1309
+ """
1310
+ An encrypted string which supports tagging and on-demand decryption.
1311
+ All methods provided by Python's built-in `str` are supported, all of which operate on the decrypted value.
1312
+ Any attempt to use this value when it cannot be decrypted will raise an exception.
1313
+ Despite supporting `str` methods, access to an instance of this type through templating is recommended over direct access.
1314
+ """
1315
+
1316
+ __slots__ = ('_ciphertext', '_plaintext', '_ansible_tags_mapping')
1317
+
1318
+ _subclasses_native_type: t.ClassVar[bool] = False
1319
+ _empty_tags_as_native: t.ClassVar[bool] = False
1320
+
1321
+ _ciphertext: str
1322
+ _plaintext: str | None
1323
+ _ansible_tags_mapping: _AnsibleTagsMapping | _EmptyROInternalTagsMapping
1324
+
1325
+ def __init__(self, *, ciphertext: str) -> None:
1326
+ if type(ciphertext) is not str: # pylint: disable=unidiomatic-typecheck
1327
+ raise TypeError(f'ciphertext must be {str} instead of {type(ciphertext)}')
1328
+
1329
+ object.__setattr__(self, '_ciphertext', ciphertext)
1330
+ object.__setattr__(self, '_plaintext', None)
1331
+ object.__setattr__(self, '_ansible_tags_mapping', _EMPTY_INTERNAL_TAGS_MAPPING)
1332
+
1333
+ @classmethod
1334
+ def _instance_factory(cls, value: t.Any, tags_mapping: _AnsibleTagsMapping) -> EncryptedString:
1335
+ instance = EncryptedString.__new__(EncryptedString)
1336
+
1337
+ # In 2.18 and earlier, vaulted values were not trusted.
1338
+ # This maintains backwards compatibility with that.
1339
+ # Additionally, supporting templating on vaulted values could be problematic for a few cases:
1340
+ # 1) There's no way to compose YAML tags, so you can't use `!unsafe` and `!vault` together.
1341
+ # 2) It would make composing `EncryptedString` with a possible future `TemplateString` more difficult.
1342
+ tags_mapping.pop(TrustedAsTemplate, None)
1343
+
1344
+ object.__setattr__(instance, '_ciphertext', value._ciphertext)
1345
+ object.__setattr__(instance, '_plaintext', value._plaintext)
1346
+ object.__setattr__(instance, '_ansible_tags_mapping', tags_mapping)
1347
+
1348
+ return instance
1349
+
1350
+ def __setstate__(self, state: tuple[None, dict[str, t.Any]]) -> None:
1351
+ for key, value in state[1].items():
1352
+ object.__setattr__(self, key, value)
1353
+
1354
+ def __delattr__(self, item: str) -> t.NoReturn:
1355
+ raise AttributeError(f'{self.__class__.__name__!r} object is read-only')
1356
+
1357
+ def __setattr__(self, key: str, value: object) -> t.NoReturn:
1358
+ raise AttributeError(f'{self.__class__.__name__!r} object is read-only')
1359
+
1360
+ @classmethod
1361
+ def _init_class(cls) -> None:
1362
+ """
1363
+ Add proxies for the specified `str` methods.
1364
+ These proxies operate on the plaintext, which is decrypted on-demand.
1365
+ """
1366
+ cls._native_type = cls
1367
+
1368
+ operator_method_names = (
1369
+ '__eq__',
1370
+ '__ge__',
1371
+ '__gt__',
1372
+ '__le__',
1373
+ '__lt__',
1374
+ '__ne__',
1375
+ )
1376
+
1377
+ method_names = (
1378
+ '__add__',
1379
+ '__contains__',
1380
+ '__format__',
1381
+ '__getitem__',
1382
+ '__hash__',
1383
+ '__iter__',
1384
+ '__len__',
1385
+ '__mod__',
1386
+ '__mul__',
1387
+ '__rmod__',
1388
+ '__rmul__',
1389
+ 'capitalize',
1390
+ 'casefold',
1391
+ 'center',
1392
+ 'count',
1393
+ 'encode',
1394
+ 'endswith',
1395
+ 'expandtabs',
1396
+ 'find',
1397
+ 'format',
1398
+ 'format_map',
1399
+ 'index',
1400
+ 'isalnum',
1401
+ 'isalpha',
1402
+ 'isascii',
1403
+ 'isdecimal',
1404
+ 'isdigit',
1405
+ 'isidentifier',
1406
+ 'islower',
1407
+ 'isnumeric',
1408
+ 'isprintable',
1409
+ 'isspace',
1410
+ 'istitle',
1411
+ 'isupper',
1412
+ 'join',
1413
+ 'ljust',
1414
+ 'lower',
1415
+ 'lstrip',
1416
+ 'maketrans', # static, but implemented for simplicity/consistency
1417
+ 'partition',
1418
+ 'removeprefix',
1419
+ 'removesuffix',
1420
+ 'replace',
1421
+ 'rfind',
1422
+ 'rindex',
1423
+ 'rjust',
1424
+ 'rpartition',
1425
+ 'rsplit',
1426
+ 'rstrip',
1427
+ 'split',
1428
+ 'splitlines',
1429
+ 'startswith',
1430
+ 'strip',
1431
+ 'swapcase',
1432
+ 'title',
1433
+ 'translate',
1434
+ 'upper',
1435
+ 'zfill',
1436
+ )
1437
+
1438
+ for method_name in operator_method_names:
1439
+ setattr(cls, method_name, functools.partialmethod(cls._proxy_str_operator_method, getattr(str, method_name)))
1440
+
1441
+ for method_name in method_names:
1442
+ setattr(cls, method_name, functools.partialmethod(cls._proxy_str_method, getattr(str, method_name)))
1443
+
1444
+ def _decrypt(self) -> str:
1445
+ """
1446
+ Attempt to decrypt the ciphertext and return the plaintext, which will be cached.
1447
+ If decryption fails an exception will be raised and no result will be cached.
1448
+ """
1449
+ if self._plaintext is None:
1450
+ vault = VaultLib(secrets=VaultSecretsContext.current().secrets)
1451
+ # use the utility method to ensure that origin tags are available
1452
+ plaintext = to_text(vault.decrypt(VaultHelper.get_ciphertext(self, with_tags=True))) # raises if the ciphertext cannot be decrypted
1453
+
1454
+ # propagate source value tags plus VaultedValue for round-tripping ciphertext
1455
+ plaintext = AnsibleTagHelper.tag(plaintext, AnsibleTagHelper.tags(self) | {VaultedValue(ciphertext=self._ciphertext)})
1456
+
1457
+ object.__setattr__(self, '_plaintext', plaintext)
1458
+
1459
+ return self._plaintext
1460
+
1461
+ def _as_dict(self) -> t.Dict[str, t.Any]:
1462
+ return dict(
1463
+ value=self._ciphertext,
1464
+ tags=list(self._ansible_tags_mapping.values()),
1465
+ )
1466
+
1467
+ def _native_copy(self) -> str:
1468
+ return AnsibleTagHelper.untag(self._decrypt())
1469
+
1470
+ def _proxy_str_operator_method(self, method: t.Callable, other) -> t.Any:
1471
+ obj = self._decrypt()
1472
+
1473
+ if type(other) is EncryptedString: # pylint: disable=unidiomatic-typecheck
1474
+ other = other._decrypt()
1475
+
1476
+ return method(obj, other)
1477
+
1478
+ def _proxy_str_method(self, method: t.Callable, *args, **kwargs) -> t.Any:
1479
+ obj = self._decrypt()
1480
+ return method(obj, *args, **kwargs)
1481
+
1482
+ def __repr__(self) -> str:
1483
+ return f'{self.__class__.__name__}(ciphertext={self._ciphertext!r})'
1484
+
1485
+ def __str__(self) -> str:
1486
+ return self._decrypt()
1487
+
1488
+ def __float__(self) -> float:
1489
+ return float(self._decrypt())
1490
+
1491
+ def __int__(self) -> int:
1492
+ return int(self._decrypt())
1493
+
1494
+ def __radd__(self, other: t.Any) -> str:
1495
+ return other + self._decrypt()
1496
+
1497
+ def __fspath__(self) -> str:
1498
+ return self._decrypt()
1499
+
1500
+
1501
+ class VaultHelper:
1502
+ """Vault specific utility methods."""
1503
+
1504
+ @staticmethod
1505
+ def get_ciphertext(value: t.Any, *, with_tags: bool) -> str | None:
1506
+ """
1507
+ If the given value is an `EncryptedString`, `VaultExceptionMarker` or tagged with `VaultedValue`, return the ciphertext, otherwise return `None`.
1508
+ Tags on the value other than `VaultedValue` will be included on the ciphertext if `with_tags` is `True`, otherwise it will be tagless.
1509
+ """
1510
+ value_type = type(value)
1511
+ ciphertext: str | None
1512
+ tags = AnsibleTagHelper.tags(value)
1513
+
1514
+ if value_type is _jinja_common.VaultExceptionMarker:
1515
+ ciphertext = value._marker_undecryptable_ciphertext
1516
+ tags = AnsibleTagHelper.tags(ciphertext) # ciphertext has tags but value does not
1517
+ elif value_type is EncryptedString:
1518
+ ciphertext = value._ciphertext
1519
+ elif value_type in _jinja_common.Marker._concrete_subclasses: # avoid wasteful raise/except of Marker when calling get_tag below
1520
+ ciphertext = None
1521
+ elif vaulted_value := VaultedValue.get_tag(value):
1522
+ ciphertext = vaulted_value.ciphertext
1523
+ else:
1524
+ ciphertext = None
1525
+
1526
+ if ciphertext:
1527
+ if with_tags:
1528
+ ciphertext = VaultedValue.untag(AnsibleTagHelper.tag(ciphertext, tags))
1529
+ else:
1530
+ ciphertext = AnsibleTagHelper.untag(ciphertext)
1531
+
1532
+ return ciphertext