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
ansible/vars/manager.py CHANGED
@@ -19,38 +19,60 @@ from __future__ import annotations
19
19
 
20
20
  import os
21
21
  import sys
22
+ import typing as t
22
23
 
23
24
  from collections import defaultdict
24
- from collections.abc import Mapping, MutableMapping, Sequence
25
- from hashlib import sha1
26
-
27
- from jinja2.exceptions import UndefinedError
25
+ from collections.abc import Mapping, MutableMapping
28
26
 
29
27
  from ansible import constants as C
30
- from ansible.errors import AnsibleError, AnsibleParserError, AnsibleUndefinedVariable, AnsibleFileNotFound, AnsibleAssertionError
28
+ from ansible.errors import (AnsibleError, AnsibleParserError, AnsibleUndefinedVariable, AnsibleFileNotFound,
29
+ AnsibleAssertionError, AnsibleValueOmittedError)
31
30
  from ansible.inventory.host import Host
32
31
  from ansible.inventory.helpers import sort_groups, get_group_vars
33
- from ansible.module_utils.common.text.converters import to_text
32
+ from ansible.inventory.manager import InventoryManager
33
+ from ansible.module_utils.datatag import native_type_name
34
34
  from ansible.module_utils.six import text_type
35
- from ansible.vars.fact_cache import FactCache
36
- from ansible.template import Templar
35
+ from ansible.module_utils.datatag import deprecate_value
36
+ from ansible.parsing.dataloader import DataLoader
37
+ from ansible._internal._templating._engine import TemplateEngine
38
+ from ansible.plugins.loader import cache_loader
37
39
  from ansible.utils.display import Display
38
40
  from ansible.utils.vars import combine_vars, load_extra_vars, load_options_vars
39
- from ansible.utils.unsafe_proxy import wrap_var
40
41
  from ansible.vars.clean import namespace_facts, clean_facts
42
+ from ansible.vars.hostvars import HostVars
41
43
  from ansible.vars.plugins import get_vars_from_inventory_sources, get_vars_from_path
42
44
  from ansible.vars.reserved import warn_if_reserved
43
45
 
46
+ if t.TYPE_CHECKING:
47
+ from ansible.playbook import Play
48
+ from ansible.playbook.task import Task
49
+
44
50
  display = Display()
45
51
 
52
+ # deprecated: description='enable top-level facts deprecation' core_version='2.20'
53
+ # _DEPRECATE_TOP_LEVEL_FACT_MSG = sys.intern('Top-level facts are deprecated, use `ansible_facts` instead.')
54
+ # _DEPRECATE_TOP_LEVEL_FACT_REMOVAL_VERSION = sys.intern('2.22')
55
+
56
+
57
+ def _deprecate_top_level_fact(value: t.Any) -> t.Any:
58
+ """
59
+ Deprecate the given top-level fact value.
60
+ The inner values are shared to aid in message de-duplication across hosts/values, and reduce intra-process memory usage.
61
+ Unique tag instances are required to achieve the correct de-duplication within a top-level templating operation.
62
+ """
63
+ # deprecated: description='enable top-level facts deprecation' core_version='2.20'
64
+ # return deprecate_value(value, _DEPRECATE_TOP_LEVEL_FACT_MSG, removal_version=_DEPRECATE_TOP_LEVEL_FACT_REMOVAL_VERSION)
65
+ return value
66
+
46
67
 
47
68
  def preprocess_vars(a):
48
- '''
69
+ """
49
70
  Ensures that vars contained in the parameter passed in are
50
71
  returned as a list of dictionaries, to ensure for instance
51
72
  that vars loaded from a file conform to an expected state.
52
- '''
73
+ """
53
74
 
75
+ # FIXME: this does not properly handle omit, undefined, or dynamic structure from templated `vars` ; templating should be done earlier
54
76
  if a is None:
55
77
  return None
56
78
  elif not isinstance(a, list):
@@ -60,7 +82,11 @@ def preprocess_vars(a):
60
82
 
61
83
  for item in data:
62
84
  if not isinstance(item, MutableMapping):
63
- raise AnsibleError("variable files must contain either a dictionary of variables, or a list of dictionaries. Got: %s (%s)" % (a, type(a)))
85
+ raise AnsibleParserError(
86
+ message="Invalid variable file contents.",
87
+ obj=item,
88
+ help_text="Variable files must contain either a dictionary of variables, or a list of dictionaries.",
89
+ )
64
90
 
65
91
  return data
66
92
 
@@ -70,16 +96,12 @@ class VariableManager:
70
96
  _ALLOWED = frozenset(['plugins_by_group', 'groups_plugins_play', 'groups_plugins_inventory', 'groups_inventory',
71
97
  'all_plugins_play', 'all_plugins_inventory', 'all_inventory'])
72
98
 
73
- def __init__(self, loader=None, inventory=None, version_info=None):
74
- self._nonpersistent_fact_cache = defaultdict(dict)
75
- self._vars_cache = defaultdict(dict)
76
- self._extra_vars = defaultdict(dict)
77
- self._host_vars_files = defaultdict(dict)
78
- self._group_vars_files = defaultdict(dict)
99
+ def __init__(self, loader: DataLoader | None = None, inventory: InventoryManager | None = None, version_info: dict[str, str] | None = None) -> None:
100
+ self._nonpersistent_fact_cache: defaultdict[str, dict] = defaultdict(dict)
101
+ self._vars_cache: defaultdict[str, dict] = defaultdict(dict)
79
102
  self._inventory = inventory
80
103
  self._loader = loader
81
- self._hostvars = None
82
- self._omit_token = '__omit_place_holder__%s' % sha1(os.urandom(64)).hexdigest()
104
+ self._hostvars: HostVars | None = None
83
105
 
84
106
  self._options_vars = load_options_vars(version_info)
85
107
 
@@ -93,41 +115,12 @@ class VariableManager:
93
115
 
94
116
  # load fact cache
95
117
  try:
96
- self._fact_cache = FactCache()
97
- except AnsibleError as e:
118
+ self._fact_cache = cache_loader.get(C.CACHE_PLUGIN)
119
+ except Exception as ex:
98
120
  # bad cache plugin is not fatal error
99
- # fallback to a dict as in memory cache
100
- display.warning(to_text(e))
101
- self._fact_cache = {}
102
-
103
- def __getstate__(self):
104
- data = dict(
105
- fact_cache=self._fact_cache,
106
- np_fact_cache=self._nonpersistent_fact_cache,
107
- vars_cache=self._vars_cache,
108
- extra_vars=self._extra_vars,
109
- host_vars_files=self._host_vars_files,
110
- group_vars_files=self._group_vars_files,
111
- omit_token=self._omit_token,
112
- options_vars=self._options_vars,
113
- inventory=self._inventory,
114
- safe_basedir=self.safe_basedir,
115
- )
116
- return data
117
-
118
- def __setstate__(self, data):
119
- self._fact_cache = data.get('fact_cache', defaultdict(dict))
120
- self._nonpersistent_fact_cache = data.get('np_fact_cache', defaultdict(dict))
121
- self._vars_cache = data.get('vars_cache', defaultdict(dict))
122
- self._extra_vars = data.get('extra_vars', dict())
123
- self._host_vars_files = data.get('host_vars_files', defaultdict(dict))
124
- self._group_vars_files = data.get('group_vars_files', defaultdict(dict))
125
- self._omit_token = data.get('omit_token', '__omit_place_holder__%s' % sha1(os.urandom(64)).hexdigest())
126
- self._inventory = data.get('inventory', None)
127
- self._options_vars = data.get('options_vars', dict())
128
- self.safe_basedir = data.get('safe_basedir', False)
129
- self._loader = None
130
- self._hostvars = None
121
+ # fallback to builtin memory cache plugin
122
+ display.error_as_warning(None, ex)
123
+ self._fact_cache = cache_loader.get('ansible.builtin.memory') # use FQCN to ensure the builtin version is used
131
124
 
132
125
  @property
133
126
  def extra_vars(self):
@@ -136,9 +129,18 @@ class VariableManager:
136
129
  def set_inventory(self, inventory):
137
130
  self._inventory = inventory
138
131
 
139
- def get_vars(self, play=None, host=None, task=None, include_hostvars=True, include_delegate_to=False, use_cache=True,
140
- _hosts=None, _hosts_all=None, stage='task'):
141
- '''
132
+ def get_vars(
133
+ self,
134
+ play: Play | None = None,
135
+ host: Host | None = None,
136
+ task: Task | None = None,
137
+ include_hostvars: bool = True,
138
+ use_cache: bool = True,
139
+ _hosts: list[str] | None = None,
140
+ _hosts_all: list[str] | None = None,
141
+ stage: str = 'task',
142
+ ) -> dict[str, t.Any]:
143
+ """
142
144
  Returns the variables, with optional "context" given via the parameters
143
145
  for the play, host, and task (which could possibly result in different
144
146
  sets of variables being returned due to the additional context).
@@ -146,7 +148,6 @@ class VariableManager:
146
148
  The order of precedence is:
147
149
  - play->roles->get_default_vars (if there is a play context)
148
150
  - group_vars_files[host] (if there is a host context)
149
- - host_vars_files[host] (if there is a host context)
150
151
  - host->get_vars (if there is a host context)
151
152
  - fact_cache[host] (if there is a host context)
152
153
  - play vars (if there is a play context)
@@ -159,16 +160,11 @@ class VariableManager:
159
160
  ``_hosts`` and ``_hosts_all`` should be considered private args, with only internal trusted callers relying
160
161
  on the functionality they provide. These arguments may be removed at a later date without a deprecation
161
162
  period and without warning.
162
- '''
163
- if include_delegate_to:
164
- display.deprecated(
165
- "`VariableManager.get_vars`'s argument `include_delegate_to` has no longer any effect.",
166
- version="2.19",
167
- )
163
+ """
168
164
 
169
165
  display.debug("in VariableManager get_vars()")
170
166
 
171
- all_vars = dict()
167
+ all_vars: dict[str, t.Any] = dict()
172
168
  magic_variables = self._get_magic_variables(
173
169
  play=play,
174
170
  host=host,
@@ -178,21 +174,11 @@ class VariableManager:
178
174
  _hosts_all=_hosts_all,
179
175
  )
180
176
 
181
- _vars_sources = {}
182
-
183
177
  def _combine_and_track(data, new_data, source):
184
- '''
185
- Wrapper function to update var sources dict and call combine_vars()
186
-
187
- See notes in the VarsWithSources docstring for caveats and limitations of the source tracking
188
- '''
178
+ # FIXME: this no longer does any tracking, only a slight optimization for empty new_data
189
179
  if new_data == {}:
190
180
  return data
191
181
 
192
- if C.DEFAULT_DEBUG:
193
- # Populate var sources dict
194
- for key in new_data:
195
- _vars_sources[key] = source
196
182
  return combine_vars(data, new_data)
197
183
 
198
184
  # default for all cases
@@ -226,33 +212,15 @@ class VariableManager:
226
212
  if host:
227
213
  # THE 'all' group and the rest of groups for a host, used below
228
214
  all_group = self._inventory.groups.get('all')
229
- host_groups = sort_groups([g for g in host.get_groups() if g.name not in ['all']])
230
-
231
- def _get_plugin_vars(plugin, path, entities):
232
- data = {}
233
- try:
234
- data = plugin.get_vars(self._loader, path, entities)
235
- except AttributeError:
236
- try:
237
- for entity in entities:
238
- if isinstance(entity, Host):
239
- data |= plugin.get_host_vars(entity.name)
240
- else:
241
- data |= plugin.get_group_vars(entity.name)
242
- except AttributeError:
243
- if hasattr(plugin, 'run'):
244
- raise AnsibleError("Cannot use v1 type vars plugin %s from %s" % (plugin._load_name, plugin._original_path))
245
- else:
246
- raise AnsibleError("Invalid vars plugin %s from %s" % (plugin._load_name, plugin._original_path))
247
- return data
215
+ host_groups = sort_groups([g for g in host.get_groups() if g.name != 'all'])
248
216
 
249
217
  # internal functions that actually do the work
250
218
  def _plugins_inventory(entities):
251
- ''' merges all entities by inventory source '''
219
+ """ merges all entities by inventory source """
252
220
  return get_vars_from_inventory_sources(self._loader, self._inventory._sources, entities, stage)
253
221
 
254
222
  def _plugins_play(entities):
255
- ''' merges all entities adjacent to play '''
223
+ """ merges all entities adjacent to play """
256
224
  data = {}
257
225
  for path in basedirs:
258
226
  data = _combine_and_track(data, get_vars_from_path(self._loader, path, entities, stage), "path '%s'" % path)
@@ -269,22 +237,22 @@ class VariableManager:
269
237
  return _plugins_play([all_group])
270
238
 
271
239
  def groups_inventory():
272
- ''' gets group vars from inventory '''
240
+ """ gets group vars from inventory """
273
241
  return get_group_vars(host_groups)
274
242
 
275
243
  def groups_plugins_inventory():
276
- ''' gets plugin sources from inventory for groups '''
244
+ """ gets plugin sources from inventory for groups """
277
245
  return _plugins_inventory(host_groups)
278
246
 
279
247
  def groups_plugins_play():
280
- ''' gets plugin sources from play for groups '''
248
+ """ gets plugin sources from play for groups """
281
249
  return _plugins_play(host_groups)
282
250
 
283
251
  def plugins_by_groups():
284
- '''
252
+ """
285
253
  merges all plugin sources by group,
286
254
  This should be used instead, NOT in combination with the other groups_plugins* functions
287
- '''
255
+ """
288
256
  data = {}
289
257
  for group in host_groups:
290
258
  data[group] = _combine_and_track(data[group], _plugins_inventory(group), "inventory group_vars for '%s'" % group)
@@ -308,15 +276,20 @@ class VariableManager:
308
276
  # finally, the facts caches for this host, if it exists
309
277
  # TODO: cleaning of facts should eventually become part of taskresults instead of vars
310
278
  try:
311
- facts = wrap_var(self._fact_cache.get(host.name, {}))
279
+ try:
280
+ facts = self._fact_cache.get(host.name)
281
+ except KeyError:
282
+ facts = {}
283
+
312
284
  all_vars |= namespace_facts(facts)
313
285
 
314
286
  # push facts to main namespace
315
287
  if C.INJECT_FACTS_AS_VARS:
316
- all_vars = _combine_and_track(all_vars, wrap_var(clean_facts(facts)), "facts")
288
+ deprecated_facts_vars = {k: _deprecate_top_level_fact(v) for k, v in clean_facts(facts).items()}
289
+ all_vars = _combine_and_track(all_vars, deprecated_facts_vars, "facts")
317
290
  else:
318
291
  # always 'promote' ansible_local
319
- all_vars = _combine_and_track(all_vars, wrap_var({'ansible_local': facts.get('ansible_local', {})}), "facts")
292
+ all_vars = _combine_and_track(all_vars, {'ansible_local': facts.get('ansible_local', {})}, "facts")
320
293
  except KeyError:
321
294
  pass
322
295
 
@@ -324,63 +297,68 @@ class VariableManager:
324
297
  all_vars = _combine_and_track(all_vars, play.get_vars(), "play vars")
325
298
 
326
299
  vars_files = play.get_vars_files()
327
- try:
328
- for vars_file_item in vars_files:
329
- # create a set of temporary vars here, which incorporate the extra
330
- # and magic vars so we can properly template the vars_files entries
331
- # NOTE: this makes them depend on host vars/facts so things like
332
- # ansible_facts['os_distribution'] can be used, ala include_vars.
333
- # Consider DEPRECATING this in the future, since we have include_vars ...
334
- temp_vars = combine_vars(all_vars, self._extra_vars)
335
- temp_vars = combine_vars(temp_vars, magic_variables)
336
- templar = Templar(loader=self._loader, variables=temp_vars)
337
-
338
- # we assume each item in the list is itself a list, as we
339
- # support "conditional includes" for vars_files, which mimics
340
- # the with_first_found mechanism.
341
- vars_file_list = vars_file_item
342
- if not isinstance(vars_file_list, list):
343
- vars_file_list = [vars_file_list]
344
-
345
- # now we iterate through the (potential) files, and break out
346
- # as soon as we read one from the list. If none are found, we
347
- # raise an error, which is silently ignored at this point.
348
- try:
349
- for vars_file in vars_file_list:
350
- vars_file = templar.template(vars_file)
351
- if not (isinstance(vars_file, Sequence)):
352
- raise AnsibleError(
353
- "Invalid vars_files entry found: %r\n"
354
- "vars_files entries should be either a string type or "
355
- "a list of string types after template expansion" % vars_file
356
- )
357
- try:
358
- play_search_stack = play.get_search_path()
359
- found_file = self._loader.path_dwim_relative_stack(play_search_stack, 'vars', vars_file)
360
- data = preprocess_vars(self._loader.load_from_file(found_file, unsafe=True, cache='vaulted'))
361
- if data is not None:
362
- for item in data:
363
- all_vars = _combine_and_track(all_vars, item, "play vars_files from '%s'" % vars_file)
364
- break
365
- except AnsibleFileNotFound:
366
- # we continue on loader failures
367
- continue
368
- except AnsibleParserError:
369
- raise
370
- except (UndefinedError, AnsibleUndefinedVariable):
371
- if host is not None and self._fact_cache.get(host.name, dict()).get('module_setup') and task is not None:
372
- raise AnsibleUndefinedVariable("an undefined variable was found when attempting to template the vars_files item '%s'"
373
- % vars_file_item, obj=vars_file_item)
374
- else:
375
- # we do not have a full context here, and the missing variable could be because of that
376
- # so just show a warning and continue
377
- display.vvv("skipping vars_file '%s' due to an undefined variable" % vars_file_item)
300
+
301
+ for vars_file_item in vars_files:
302
+ # create a set of temporary vars here, which incorporate the extra
303
+ # and magic vars so we can properly template the vars_files entries
304
+ # NOTE: this makes them depend on host vars/facts so things like
305
+ # ansible_facts['os_distribution'] can be used, ala include_vars.
306
+ # Consider DEPRECATING this in the future, since we have include_vars ...
307
+ temp_vars = combine_vars(all_vars, self._extra_vars)
308
+ temp_vars = combine_vars(temp_vars, magic_variables)
309
+ templar = TemplateEngine(loader=self._loader, variables=temp_vars)
310
+
311
+ # we assume each item in the list is itself a list, as we
312
+ # support "conditional includes" for vars_files, which mimics
313
+ # the with_first_found mechanism.
314
+ vars_file_list = vars_file_item
315
+ if not isinstance(vars_file_list, list):
316
+ vars_file_list = [vars_file_list]
317
+
318
+ # now we iterate through the (potential) files, and break out
319
+ # as soon as we read one from the list. If none are found, we
320
+ # raise an error, which is silently ignored at this point.
321
+ try:
322
+ for vars_file in vars_file_list:
323
+ vars_file = templar.template(vars_file)
324
+ if not (isinstance(vars_file, str)):
325
+ raise AnsibleParserError(
326
+ message=f"Invalid `vars_files` value of type {native_type_name(vars_file)!r}.",
327
+ obj=vars_file,
328
+ help_text="A `vars_files` value should either be a string or list of strings.",
329
+ )
330
+ try:
331
+ play_search_stack = play.get_search_path()
332
+ found_file = self._loader.path_dwim_relative_stack(play_search_stack, 'vars', vars_file)
333
+ data = preprocess_vars(self._loader.load_from_file(found_file, unsafe=True, cache='vaulted', trusted_as_template=True))
334
+ if data is not None:
335
+ for item in data:
336
+ all_vars = _combine_and_track(all_vars, item, "play vars_files from '%s'" % vars_file)
337
+ display.vvv(f"Read `vars_file` {found_file!r}.")
338
+ break
339
+ except AnsibleFileNotFound:
340
+ # we continue on loader failures
378
341
  continue
342
+ except AnsibleParserError:
343
+ raise
344
+ except AnsibleUndefinedVariable:
345
+ raise
346
+ except Exception as ex:
347
+ raise AnsibleParserError(f"Error reading `vars_files` file {vars_file!r}.", obj=vars_file) from ex
348
+
349
+ except AnsibleUndefinedVariable as ex:
350
+ if host is not None:
351
+ try:
352
+ facts = self._fact_cache.get(host.name)
353
+ except KeyError:
354
+ pass
355
+ else:
356
+ if facts.get('module_setup') and task is not None:
357
+ raise AnsibleUndefinedVariable("an undefined variable was found when attempting to template the vars_files item '%s'"
358
+ % vars_file_item, obj=vars_file_item) from ex
379
359
 
380
- display.vvv("Read vars_file '%s'" % vars_file_item)
381
- except TypeError:
382
- raise AnsibleParserError("Error while reading vars files - please supply a list of file names. "
383
- "Got '%s' of type %s" % (vars_files, type(vars_files)))
360
+ display.warning("skipping vars_file item due to an undefined variable", obj=vars_file_item)
361
+ continue
384
362
 
385
363
  # We now merge in all exported vars from all roles in the play (very high precedence)
386
364
  for role in play.roles:
@@ -433,17 +411,21 @@ class VariableManager:
433
411
  all_vars['vars'] = all_vars.copy()
434
412
 
435
413
  display.debug("done with get_vars()")
436
- if C.DEFAULT_DEBUG:
437
- # Use VarsWithSources wrapper class to display var sources
438
- return VarsWithSources.new_vars_with_sources(all_vars, _vars_sources)
439
- else:
440
- return all_vars
414
+ return all_vars
415
+
416
+ def _facts_gathered_for_host(self, hostname) -> bool:
417
+ try:
418
+ facts = self._fact_cache.get(hostname)
419
+ except KeyError:
420
+ facts = {}
421
+
422
+ return bool(facts.get('_ansible_facts_gathered', False))
441
423
 
442
424
  def _get_magic_variables(self, play, host, task, include_hostvars, _hosts=None, _hosts_all=None):
443
- '''
425
+ """
444
426
  Returns a dictionary of so-called "magic" variables in Ansible,
445
427
  which are special variables we set internally for use.
446
- '''
428
+ """
447
429
 
448
430
  variables = {}
449
431
  variables['playbook_dir'] = os.path.abspath(self._loader.get_basedir())
@@ -480,13 +462,13 @@ class VariableManager:
480
462
  if self._inventory is not None:
481
463
  variables['groups'] = self._inventory.get_groups_dict()
482
464
  if play:
483
- templar = Templar(loader=self._loader)
484
- if not play.finalized and templar.is_template(play.hosts):
485
- pattern = 'all'
486
- else:
487
- pattern = play.hosts or 'all'
488
465
  # add the list of hosts in the play, as adjusted for limit/filters
489
466
  if not _hosts_all:
467
+ if not play.finalized and TemplateEngine().is_template(play.hosts):
468
+ pattern = 'all'
469
+ else:
470
+ pattern = play.hosts or 'all'
471
+
490
472
  _hosts_all = [h.name for h in self._inventory.get_hosts(pattern=pattern, ignore_restrictions=True)]
491
473
  if not _hosts:
492
474
  _hosts = [h.name for h in self._inventory.get_hosts()]
@@ -495,12 +477,13 @@ class VariableManager:
495
477
  variables['ansible_play_hosts'] = [x for x in variables['ansible_play_hosts_all'] if x not in play._removed_hosts]
496
478
  variables['ansible_play_batch'] = [x for x in _hosts if x not in play._removed_hosts]
497
479
 
498
- # DEPRECATED: play_hosts should be deprecated in favor of ansible_play_batch,
499
- # however this would take work in the templating engine, so for now we'll add both
500
- variables['play_hosts'] = variables['ansible_play_batch']
480
+ variables['play_hosts'] = deprecate_value(
481
+ value=variables['ansible_play_batch'],
482
+ msg='The `play_hosts` magic variable is deprecated.',
483
+ removal_version='2.23',
484
+ help_text='Use `ansible_play_batch` instead.',
485
+ )
501
486
 
502
- # the 'omit' value allows params to be left out if the variable they are based on is undefined
503
- variables['omit'] = self._omit_token
504
487
  # Set options vars
505
488
  for option, option_value in self._options_vars.items():
506
489
  variables[option] = option_value
@@ -517,56 +500,64 @@ class VariableManager:
517
500
  Not used directly be VariableManager, but used primarily within TaskExecutor
518
501
  """
519
502
  delegated_vars = {}
520
- delegated_host_name = None
521
- if task.delegate_to:
522
- delegated_host_name = templar.template(task.delegate_to, fail_on_undefined=False)
503
+ delegated_host_name = ... # sentinel value distinct from empty/None, which are errors
523
504
 
524
- # no need to do work if omitted
525
- if delegated_host_name != self._omit_token:
526
-
527
- if not delegated_host_name:
528
- raise AnsibleError('Empty hostname produced from delegate_to: "%s"' % task.delegate_to)
505
+ if task.delegate_to:
506
+ try:
507
+ delegated_host_name = templar.template(task.delegate_to)
508
+ except AnsibleValueOmittedError:
509
+ pass
529
510
 
530
- delegated_host = self._inventory.get_host(delegated_host_name)
531
- if delegated_host is None:
532
- for h in self._inventory.get_hosts(ignore_limits=True, ignore_restrictions=True):
533
- # check if the address matches, or if both the delegated_to host
534
- # and the current host are in the list of localhost aliases
535
- if h.address == delegated_host_name:
536
- delegated_host = h
537
- break
538
- else:
539
- delegated_host = Host(name=delegated_host_name)
540
-
541
- delegated_vars['ansible_delegated_vars'] = {
542
- delegated_host_name: self.get_vars(
543
- play=task.get_play(),
544
- host=delegated_host,
545
- task=task,
546
- include_hostvars=True,
547
- )
548
- }
549
- delegated_vars['ansible_delegated_vars'][delegated_host_name]['inventory_hostname'] = variables.get('inventory_hostname')
511
+ # bypass for unspecified value/omit
512
+ if delegated_host_name is ...:
513
+ return delegated_vars, None
514
+
515
+ if not delegated_host_name:
516
+ raise AnsibleError('Empty hostname produced from delegate_to: "%s"' % task.delegate_to)
517
+
518
+ delegated_host = self._inventory.get_host(delegated_host_name)
519
+ if delegated_host is None:
520
+ for h in self._inventory.get_hosts(ignore_limits=True, ignore_restrictions=True):
521
+ # check if the address matches, or if both the delegated_to host
522
+ # and the current host are in the list of localhost aliases
523
+ if h.address == delegated_host_name:
524
+ delegated_host = h
525
+ break
526
+ else:
527
+ delegated_host = Host(name=delegated_host_name)
528
+
529
+ delegated_vars['ansible_delegated_vars'] = {
530
+ delegated_host_name: self.get_vars(
531
+ play=task.get_play(),
532
+ host=delegated_host,
533
+ task=task,
534
+ include_hostvars=True,
535
+ )
536
+ }
537
+ delegated_vars['ansible_delegated_vars'][delegated_host_name]['inventory_hostname'] = variables.get('inventory_hostname')
550
538
 
551
539
  return delegated_vars, delegated_host_name
552
540
 
553
541
  def clear_facts(self, hostname):
554
- '''
542
+ """
555
543
  Clears the facts for a host
556
- '''
557
- self._fact_cache.pop(hostname, None)
544
+ """
545
+ try:
546
+ self._fact_cache.delete(hostname)
547
+ except KeyError:
548
+ pass
558
549
 
559
550
  def set_host_facts(self, host, facts):
560
- '''
551
+ """
561
552
  Sets or updates the given facts for a host in the fact cache.
562
- '''
553
+ """
563
554
 
564
555
  if not isinstance(facts, Mapping):
565
556
  raise AnsibleAssertionError("the type of 'facts' to set for host_facts should be a Mapping but is a %s" % type(facts))
566
557
 
567
558
  warn_if_reserved(facts.keys())
568
559
  try:
569
- host_cache = self._fact_cache[host]
560
+ host_cache = self._fact_cache.get(host)
570
561
  except KeyError:
571
562
  # We get to set this as new
572
563
  host_cache = facts
@@ -578,12 +569,12 @@ class VariableManager:
578
569
  host_cache |= facts
579
570
 
580
571
  # Save the facts back to the backing store
581
- self._fact_cache[host] = host_cache
572
+ self._fact_cache.set(host, host_cache)
582
573
 
583
574
  def set_nonpersistent_facts(self, host, facts):
584
- '''
575
+ """
585
576
  Sets or updates the given facts for a host in the fact cache.
586
- '''
577
+ """
587
578
 
588
579
  if not isinstance(facts, Mapping):
589
580
  raise AnsibleAssertionError("the type of 'facts' to set for nonpersistent_facts should be a Mapping but is a %s" % type(facts))
@@ -602,75 +593,8 @@ class VariableManager:
602
593
  warn_if_reserved([varname])
603
594
  if host not in self._vars_cache:
604
595
  self._vars_cache[host] = dict()
596
+
605
597
  if varname in self._vars_cache[host] and isinstance(self._vars_cache[host][varname], MutableMapping) and isinstance(value, MutableMapping):
606
598
  self._vars_cache[host] = combine_vars(self._vars_cache[host], {varname: value})
607
599
  else:
608
600
  self._vars_cache[host][varname] = value
609
-
610
-
611
- class VarsWithSources(MutableMapping):
612
- '''
613
- Dict-like class for vars that also provides source information for each var
614
-
615
- This class can only store the source for top-level vars. It does no tracking
616
- on its own, just shows a debug message with the information that it is provided
617
- when a particular var is accessed.
618
- '''
619
- def __init__(self, *args, **kwargs):
620
- ''' Dict-compatible constructor '''
621
- self.data = dict(*args, **kwargs)
622
- self.sources = {}
623
-
624
- @classmethod
625
- def new_vars_with_sources(cls, data, sources):
626
- ''' Alternate constructor method to instantiate class with sources '''
627
- v = cls(data)
628
- v.sources = sources
629
- return v
630
-
631
- def get_source(self, key):
632
- return self.sources.get(key, None)
633
-
634
- def __getitem__(self, key):
635
- val = self.data[key]
636
- # See notes in the VarsWithSources docstring for caveats and limitations of the source tracking
637
- display.debug("variable '%s' from source: %s" % (key, self.sources.get(key, "unknown")))
638
- return val
639
-
640
- def __setitem__(self, key, value):
641
- self.data[key] = value
642
-
643
- def __delitem__(self, key):
644
- del self.data[key]
645
-
646
- def __iter__(self):
647
- return iter(self.data)
648
-
649
- def __len__(self):
650
- return len(self.data)
651
-
652
- # Prevent duplicate debug messages by defining our own __contains__ pointing at the underlying dict
653
- def __contains__(self, key):
654
- return self.data.__contains__(key)
655
-
656
- def copy(self):
657
- return VarsWithSources.new_vars_with_sources(self.data.copy(), self.sources.copy())
658
-
659
- def __or__(self, other):
660
- if isinstance(other, MutableMapping):
661
- c = self.data.copy()
662
- c.update(other)
663
- return c
664
- return NotImplemented
665
-
666
- def __ror__(self, other):
667
- if isinstance(other, MutableMapping):
668
- c = self.__class__()
669
- c.update(other)
670
- c.update(self.data)
671
- return c
672
- return NotImplemented
673
-
674
- def __ior__(self, other):
675
- self.data.update(other)
676
- return self.data