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
@@ -17,24 +17,30 @@
17
17
 
18
18
  from __future__ import annotations
19
19
 
20
+ import functools
20
21
  import hashlib
21
22
  import os
22
23
  import string
24
+ import typing as t
23
25
 
24
26
  from collections.abc import Mapping
25
27
 
26
- from ansible.errors import AnsibleError, AnsibleParserError
28
+ from ansible import template as _template
29
+ from ansible.errors import AnsibleError, AnsibleParserError, AnsibleValueOmittedError
27
30
  from ansible.inventory.group import to_safe_group_name as original_safe
31
+ from ansible.module_utils._internal import _plugin_exec_context
28
32
  from ansible.parsing.utils.addresses import parse_address
29
- from ansible.plugins import AnsiblePlugin
30
- from ansible.plugins.cache import CachePluginAdjudicator as CacheObject
33
+ from ansible.parsing.dataloader import DataLoader
34
+ from ansible.plugins import AnsiblePlugin, _ConfigurablePlugin
35
+ from ansible.plugins.cache import CachePluginAdjudicator
31
36
  from ansible.module_utils.common.text.converters import to_bytes, to_native
32
- from ansible.module_utils.parsing.convert_bool import boolean
33
37
  from ansible.module_utils.six import string_types
34
- from ansible.template import Templar
35
38
  from ansible.utils.display import Display
36
39
  from ansible.utils.vars import combine_vars, load_extra_vars
37
40
 
41
+ if t.TYPE_CHECKING:
42
+ from ansible.inventory.data import InventoryData
43
+
38
44
  display = Display()
39
45
 
40
46
 
@@ -45,17 +51,17 @@ def to_safe_group_name(name):
45
51
 
46
52
 
47
53
  def detect_range(line=None):
48
- '''
54
+ """
49
55
  A helper function that checks a given host line to see if it contains
50
56
  a range pattern described in the docstring above.
51
57
 
52
58
  Returns True if the given line contains a pattern, else False.
53
- '''
59
+ """
54
60
  return '[' in line
55
61
 
56
62
 
57
63
  def expand_hostname_range(line=None):
58
- '''
64
+ """
59
65
  A helper function that expands a given line that contains a pattern
60
66
  specified in top docstring, and returns a list that consists of the
61
67
  expanded version.
@@ -65,7 +71,7 @@ def expand_hostname_range(line=None):
65
71
  string splitting.
66
72
 
67
73
  References: https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html#hosts-and-groups
68
- '''
74
+ """
69
75
  all_hosts = []
70
76
  if line:
71
77
  # A hostname such as db[1:6]-node is considered to consists
@@ -127,8 +133,11 @@ def expand_hostname_range(line=None):
127
133
 
128
134
 
129
135
  def get_cache_plugin(plugin_name, **kwargs):
136
+ if not plugin_name:
137
+ raise AnsibleError("A cache plugin must be configured to use inventory caching.")
138
+
130
139
  try:
131
- cache = CacheObject(plugin_name, **kwargs)
140
+ cache = CachePluginAdjudicator(plugin_name, **kwargs)
132
141
  except AnsibleError as e:
133
142
  if 'fact_caching_connection' in to_native(e):
134
143
  raise AnsibleError("error, '%s' inventory cache plugin requires the one of the following to be set "
@@ -136,17 +145,22 @@ def get_cache_plugin(plugin_name, **kwargs):
136
145
  "[inventory]: cache_connection;\nEnvironment:\nANSIBLE_INVENTORY_CACHE_CONNECTION,\n"
137
146
  "ANSIBLE_CACHE_PLUGIN_CONNECTION." % plugin_name)
138
147
  else:
139
- raise e
148
+ raise
140
149
 
141
- if plugin_name != 'memory' and kwargs and not getattr(cache._plugin, '_options', None):
150
+ if cache._plugin.ansible_name != 'ansible.builtin.memory' and kwargs and not getattr(cache._plugin, '_options', None):
142
151
  raise AnsibleError('Unable to use cache plugin {0} for inventory. Cache options were provided but may not reconcile '
143
152
  'correctly unless set via set_options. Refer to the porting guide if the plugin derives user settings '
144
153
  'from ansible.constants.'.format(plugin_name))
145
154
  return cache
146
155
 
147
156
 
148
- class BaseInventoryPlugin(AnsiblePlugin):
149
- """ Parses an Inventory Source"""
157
+ class _BaseInventoryPlugin(AnsiblePlugin):
158
+ """
159
+ Internal base implementation for inventory plugins.
160
+
161
+ Do not inherit from this directly, use one of its public subclasses instead.
162
+ Used to introduce an extra layer in the class hierarchy to allow Constructed to subclass this while remaining a mixin for existing inventory plugins.
163
+ """
150
164
 
151
165
  TYPE = 'generator'
152
166
 
@@ -156,17 +170,27 @@ class BaseInventoryPlugin(AnsiblePlugin):
156
170
  # it by default.
157
171
  _sanitize_group_name = staticmethod(to_safe_group_name)
158
172
 
159
- def __init__(self):
173
+ def __init__(self) -> None:
160
174
 
161
- super(BaseInventoryPlugin, self).__init__()
175
+ super().__init__()
162
176
 
163
177
  self._options = {}
164
- self.inventory = None
165
178
  self.display = display
166
- self._vars = {}
167
179
 
168
- def parse(self, inventory, loader, path, cache=True):
169
- ''' Populates inventory from the given data. Raises an error on any parse failure
180
+ # These attributes are set by the parse() method on this (base) class.
181
+ self.loader: DataLoader | None = None
182
+ self.inventory: InventoryData | None = None
183
+ self._vars: dict[str, t.Any] | None = None
184
+
185
+ trusted_by_default: bool = False
186
+ """Inventory plugins that only source templates from trusted sources can set this True to have trust automatically applied to all templates."""
187
+
188
+ @functools.cached_property
189
+ def templar(self) -> _template.Templar:
190
+ return _template.Templar(loader=self.loader)
191
+
192
+ def parse(self, inventory: InventoryData, loader: DataLoader, path: str, cache: bool = True) -> None:
193
+ """ Populates inventory from the given data. Raises an error on any parse failure
170
194
  :arg inventory: a copy of the previously accumulated inventory data,
171
195
  to be updated with any new data this plugin provides.
172
196
  The inventory can be empty if no other source/plugin ran successfully.
@@ -177,20 +201,18 @@ class BaseInventoryPlugin(AnsiblePlugin):
177
201
  but it can also be a raw string for this plugin to consume
178
202
  :arg cache: a boolean that indicates if the plugin should use the cache or not
179
203
  you can ignore if this plugin does not implement caching.
180
- '''
181
-
204
+ """
182
205
  self.loader = loader
183
206
  self.inventory = inventory
184
- self.templar = Templar(loader=loader)
185
207
  self._vars = load_extra_vars(loader)
186
208
 
187
209
  def verify_file(self, path):
188
- ''' Verify if file is usable by this plugin, base does minimal accessibility check
210
+ """ Verify if file is usable by this plugin, base does minimal accessibility check
189
211
  :arg path: a string that was passed as an inventory source,
190
212
  it normally is a path to a config file, but this is not a requirement,
191
213
  it can also be parsed itself as the inventory data to process.
192
214
  So only call this base class if you expect it to be a file.
193
- '''
215
+ """
194
216
 
195
217
  valid = False
196
218
  b_path = to_bytes(path, errors='surrogate_or_strict')
@@ -210,15 +232,14 @@ class BaseInventoryPlugin(AnsiblePlugin):
210
232
  self.inventory.set_variable(host, k, variables[k])
211
233
 
212
234
  def _read_config_data(self, path):
213
- ''' validate config and set options as appropriate
235
+ """ validate config and set options as appropriate
214
236
  :arg path: path to common yaml format config file for this plugin
215
- '''
237
+ """
216
238
 
217
- config = {}
218
239
  try:
219
240
  # avoid loader cache so meta: refresh_inventory can pick up config changes
220
241
  # if we read more than once, fs cache should be good enough
221
- config = self.loader.load_from_file(path, cache='none')
242
+ config = self.loader.load_from_file(path, cache='none', trusted_as_template=True)
222
243
  except Exception as e:
223
244
  raise AnsibleParserError(to_native(e))
224
245
 
@@ -244,20 +265,20 @@ class BaseInventoryPlugin(AnsiblePlugin):
244
265
  return config
245
266
 
246
267
  def _consume_options(self, data):
247
- ''' update existing options from alternate configuration sources not normally used by Ansible.
268
+ """ update existing options from alternate configuration sources not normally used by Ansible.
248
269
  Many API libraries already have existing configuration sources, this allows plugin author to leverage them.
249
270
  :arg data: key/value pairs that correspond to configuration options for this plugin
250
- '''
271
+ """
251
272
 
252
273
  for k in self._options:
253
274
  if k in data:
254
275
  self._options[k] = data.pop(k)
255
276
 
256
277
  def _expand_hostpattern(self, hostpattern):
257
- '''
278
+ """
258
279
  Takes a single host pattern and returns a list of hostnames and an
259
280
  optional port number that applies to all of them.
260
- '''
281
+ """
261
282
  # Can the given hostpattern be parsed as a host with an optional port
262
283
  # specification?
263
284
 
@@ -279,7 +300,11 @@ class BaseInventoryPlugin(AnsiblePlugin):
279
300
  return (hostnames, port)
280
301
 
281
302
 
282
- class BaseFileInventoryPlugin(BaseInventoryPlugin):
303
+ class BaseInventoryPlugin(_BaseInventoryPlugin):
304
+ """ Parses an Inventory Source """
305
+
306
+
307
+ class BaseFileInventoryPlugin(_BaseInventoryPlugin):
283
308
  """ Parses a File based Inventory Source"""
284
309
 
285
310
  TYPE = 'storage'
@@ -289,51 +314,44 @@ class BaseFileInventoryPlugin(BaseInventoryPlugin):
289
314
  super(BaseFileInventoryPlugin, self).__init__()
290
315
 
291
316
 
292
- class Cacheable(object):
317
+ class Cacheable(_plugin_exec_context.HasPluginInfo, _ConfigurablePlugin):
318
+ """Mixin for inventory plugins which support caching."""
293
319
 
294
- _cache = CacheObject()
320
+ _cache: CachePluginAdjudicator
295
321
 
296
322
  @property
297
- def cache(self):
323
+ def cache(self) -> CachePluginAdjudicator:
298
324
  return self._cache
299
325
 
300
- def load_cache_plugin(self):
326
+ def load_cache_plugin(self) -> None:
301
327
  plugin_name = self.get_option('cache_plugin')
302
328
  cache_option_keys = [('_uri', 'cache_connection'), ('_timeout', 'cache_timeout'), ('_prefix', 'cache_prefix')]
303
329
  cache_options = dict((opt[0], self.get_option(opt[1])) for opt in cache_option_keys if self.get_option(opt[1]) is not None)
304
330
  self._cache = get_cache_plugin(plugin_name, **cache_options)
305
331
 
306
- def get_cache_key(self, path):
307
- return "{0}_{1}".format(self.NAME, self._get_cache_prefix(path))
308
-
309
- def _get_cache_prefix(self, path):
310
- ''' create predictable unique prefix for plugin/inventory '''
311
-
312
- m = hashlib.sha1()
313
- m.update(to_bytes(self.NAME, errors='surrogate_or_strict'))
314
- d1 = m.hexdigest()
315
-
316
- n = hashlib.sha1()
317
- n.update(to_bytes(path, errors='surrogate_or_strict'))
318
- d2 = n.hexdigest()
332
+ def get_cache_key(self, path: str) -> str:
333
+ return f'{self.ansible_name}_{self._get_cache_prefix(path)}'
319
334
 
320
- return 's_'.join([d1[:5], d2[:5]])
335
+ def _get_cache_prefix(self, path: str) -> str:
336
+ """Return a predictable unique key based on the given path."""
337
+ # DTFIX-RELEASE: choose a better hashing approach
338
+ return 'k' + hashlib.sha256(f'{self.ansible_name}{path}'.encode(), usedforsecurity=False).hexdigest()[:6]
321
339
 
322
- def clear_cache(self):
323
- self._cache.flush()
340
+ def clear_cache(self) -> None:
341
+ self._cache.clear()
324
342
 
325
- def update_cache_if_changed(self):
343
+ def update_cache_if_changed(self) -> None:
326
344
  self._cache.update_cache_if_changed()
327
345
 
328
- def set_cache_plugin(self):
346
+ def set_cache_plugin(self) -> None:
329
347
  self._cache.set_cache()
330
348
 
331
349
 
332
- class Constructable(object):
333
-
334
- def _compose(self, template, variables, disable_lookups=True):
335
- ''' helper method for plugins to compose variables for Ansible based on jinja2 expression and inventory vars'''
336
- t = self.templar
350
+ class Constructable(_BaseInventoryPlugin):
351
+ def _compose(self, template, variables, disable_lookups=...):
352
+ """ helper method for plugins to compose variables for Ansible based on jinja2 expression and inventory vars"""
353
+ if disable_lookups is not ...:
354
+ self.display.deprecated("The disable_lookups arg has no effect.", version="2.23")
337
355
 
338
356
  try:
339
357
  use_extra = self.get_option('use_extra_vars')
@@ -341,15 +359,14 @@ class Constructable(object):
341
359
  use_extra = False
342
360
 
343
361
  if use_extra:
344
- t.available_variables = combine_vars(variables, self._vars)
362
+ self.templar.available_variables = combine_vars(variables, self._vars)
345
363
  else:
346
- t.available_variables = variables
364
+ self.templar.available_variables = variables
347
365
 
348
- return t.template('%s%s%s' % (t.environment.variable_start_string, template, t.environment.variable_end_string),
349
- disable_lookups=disable_lookups)
366
+ return self.templar.evaluate_expression(template)
350
367
 
351
368
  def _set_composite_vars(self, compose, variables, host, strict=False):
352
- ''' loops over compose entries to create vars for hosts '''
369
+ """ loops over compose entries to create vars for hosts """
353
370
  if compose and isinstance(compose, dict):
354
371
  for varname in compose:
355
372
  try:
@@ -361,17 +378,17 @@ class Constructable(object):
361
378
  self.inventory.set_variable(host, varname, composite)
362
379
 
363
380
  def _add_host_to_composed_groups(self, groups, variables, host, strict=False, fetch_hostvars=True):
364
- ''' helper to create complex groups for plugins based on jinja2 conditionals, hosts that meet the conditional are added to group'''
381
+ """ helper to create complex groups for plugins based on jinja2 conditionals, hosts that meet the conditional are added to group"""
365
382
  # process each 'group entry'
366
383
  if groups and isinstance(groups, dict):
367
384
  if fetch_hostvars:
368
385
  variables = combine_vars(variables, self.inventory.get_host(host).get_vars())
369
386
  self.templar.available_variables = variables
370
387
  for group_name in groups:
371
- conditional = "{%% if %s %%} True {%% else %%} False {%% endif %%}" % groups[group_name]
388
+ conditional = groups[group_name]
372
389
  group_name = self._sanitize_group_name(group_name)
373
390
  try:
374
- result = boolean(self.templar.template(conditional))
391
+ result = self.templar.evaluate_conditional(conditional)
375
392
  except Exception as e:
376
393
  if strict:
377
394
  raise AnsibleParserError("Could not add host %s to group %s: %s" % (host, group_name, to_native(e)))
@@ -384,7 +401,7 @@ class Constructable(object):
384
401
  self.inventory.add_child(group_name, host)
385
402
 
386
403
  def _add_host_to_keyed_groups(self, keys, variables, host, strict=False, fetch_hostvars=True):
387
- ''' helper to create groups for plugins based on variable values and add the corresponding hosts to it'''
404
+ """ helper to create groups for plugins based on variable values and add the corresponding hosts to it"""
388
405
  if keys and isinstance(keys, list):
389
406
  for keyed in keys:
390
407
  if keyed and isinstance(keyed, dict):
@@ -405,13 +422,16 @@ class Constructable(object):
405
422
  prefix = keyed.get('prefix', '')
406
423
  sep = keyed.get('separator', '_')
407
424
  raw_parent_name = keyed.get('parent_group', None)
408
- if raw_parent_name:
409
- try:
410
- raw_parent_name = self.templar.template(raw_parent_name)
411
- except AnsibleError as e:
412
- if strict:
413
- raise AnsibleParserError("Could not generate parent group %s for group %s: %s" % (raw_parent_name, key, to_native(e)))
414
- continue
425
+
426
+ try:
427
+ raw_parent_name = self.templar.template(raw_parent_name)
428
+ except AnsibleValueOmittedError:
429
+ raw_parent_name = None
430
+ except Exception as ex:
431
+ if strict:
432
+ raise AnsibleParserError(f'Could not generate parent group {raw_parent_name!r} for group {key!r}: {ex}') from ex
433
+
434
+ continue
415
435
 
416
436
  new_raw_group_names = []
417
437
  if isinstance(key, string_types):
@@ -3,22 +3,22 @@
3
3
 
4
4
  from __future__ import annotations
5
5
 
6
- DOCUMENTATION = '''
6
+ DOCUMENTATION = """
7
7
  name: advanced_host_list
8
8
  version_added: "2.4"
9
9
  short_description: Parses a 'host list' with ranges
10
10
  description:
11
11
  - Parses a host list string as a comma separated values of hosts and supports host ranges.
12
12
  - This plugin only applies to inventory sources that are not paths and contain at least one comma.
13
- '''
13
+ """
14
14
 
15
- EXAMPLES = '''
15
+ EXAMPLES = """
16
16
  # simple range
17
17
  # ansible -i 'host[1:10],' -m ping
18
18
 
19
19
  # still supports w/o ranges also
20
20
  # ansible-playbook -i 'localhost,' play.yml
21
- '''
21
+ """
22
22
 
23
23
  import os
24
24
 
@@ -31,6 +31,8 @@ class InventoryModule(BaseInventoryPlugin):
31
31
 
32
32
  NAME = 'advanced_host_list'
33
33
 
34
+ # advanced_host_list does not set vars, so needs no special trust assistance from the inventory API
35
+
34
36
  def verify_file(self, host_list):
35
37
 
36
38
  valid = False
@@ -40,7 +42,7 @@ class InventoryModule(BaseInventoryPlugin):
40
42
  return valid
41
43
 
42
44
  def parse(self, inventory, loader, host_list, cache=True):
43
- ''' parses the inventory file '''
45
+ """ parses the inventory file """
44
46
 
45
47
  super(InventoryModule, self).parse(inventory, loader, host_list)
46
48
 
@@ -3,7 +3,7 @@
3
3
 
4
4
  from __future__ import annotations
5
5
 
6
- DOCUMENTATION = '''
6
+ DOCUMENTATION = """
7
7
  name: auto
8
8
  author:
9
9
  - Matt Davis (@nitzmahone)
@@ -14,12 +14,12 @@ DOCUMENTATION = '''
14
14
  C(plugin) key at its root will automatically cause the named plugin to be loaded and executed with that
15
15
  config. This effectively provides automatic enabling of all installed/accessible inventory plugins.
16
16
  - To disable this behavior, remove C(auto) from the C(INVENTORY_ENABLED) config element.
17
- '''
17
+ """
18
18
 
19
- EXAMPLES = '''
19
+ EXAMPLES = """
20
20
  # This plugin is not intended for direct use; it is a fallback mechanism for automatic enabling of
21
21
  # all installed inventory plugins.
22
- '''
22
+ """
23
23
 
24
24
  from ansible.errors import AnsibleParserError
25
25
  from ansible.plugins.inventory import BaseInventoryPlugin
@@ -30,6 +30,8 @@ class InventoryModule(BaseInventoryPlugin):
30
30
 
31
31
  NAME = 'auto'
32
32
 
33
+ # no need to set trusted_by_default, since the consumers of this value will always consult the real plugin substituted during our parse()
34
+
33
35
  def verify_file(self, path):
34
36
  if not path.endswith('.yml') and not path.endswith('.yaml'):
35
37
  return False
@@ -55,6 +57,11 @@ class InventoryModule(BaseInventoryPlugin):
55
57
  raise AnsibleParserError("inventory source '{0}' could not be verified by inventory plugin '{1}'".format(path, plugin_name))
56
58
 
57
59
  self.display.v("Using inventory plugin '{0}' to process inventory source '{1}'".format(plugin._load_name, path))
60
+
61
+ # unfortunate magic to swap the real plugin type we're proxying here into the inventory data API wrapper, so the wrapper can make the right compat
62
+ # decisions based on the metadata the real plugin provides instead of our metadata
63
+ inventory._target_plugin = plugin
64
+
58
65
  plugin.parse(inventory, loader, path, cache=cache)
59
66
  try:
60
67
  plugin.update_cache_if_changed()
@@ -3,7 +3,7 @@
3
3
 
4
4
  from __future__ import annotations
5
5
 
6
- DOCUMENTATION = '''
6
+ DOCUMENTATION = """
7
7
  name: constructed
8
8
  version_added: "2.4"
9
9
  short_description: Uses Jinja2 to construct vars and groups based on existing inventory.
@@ -33,9 +33,9 @@ DOCUMENTATION = '''
33
33
  version_added: '2.11'
34
34
  extends_documentation_fragment:
35
35
  - constructed
36
- '''
36
+ """
37
37
 
38
- EXAMPLES = r'''
38
+ EXAMPLES = r"""
39
39
  # inventory.config file in YAML format
40
40
  plugin: ansible.builtin.constructed
41
41
  strict: False
@@ -77,17 +77,16 @@ EXAMPLES = r'''
77
77
  # this creates a common parent group for all ec2 availability zones
78
78
  - key: placement.availability_zone
79
79
  parent_group: all_ec2_zones
80
- '''
80
+ """
81
81
 
82
82
  import os
83
83
 
84
84
  from ansible import constants as C
85
- from ansible.errors import AnsibleParserError, AnsibleOptionsError
85
+ from ansible.errors import AnsibleParserError
86
86
  from ansible.inventory.helpers import get_group_vars
87
87
  from ansible.plugins.inventory import BaseInventoryPlugin, Constructable
88
- from ansible.module_utils.common.text.converters import to_native
88
+ from ansible.plugins.loader import cache_loader
89
89
  from ansible.utils.vars import combine_vars
90
- from ansible.vars.fact_cache import FactCache
91
90
  from ansible.vars.plugins import get_vars_from_inventory_sources
92
91
 
93
92
 
@@ -96,11 +95,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
96
95
 
97
96
  NAME = 'constructed'
98
97
 
99
- def __init__(self):
100
-
101
- super(InventoryModule, self).__init__()
102
-
103
- self._cache = FactCache()
98
+ # implicit trust behavior is already added by the YAML parser invoked by the loader
104
99
 
105
100
  def verify_file(self, path):
106
101
 
@@ -114,11 +109,11 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
114
109
  return valid
115
110
 
116
111
  def get_all_host_vars(self, host, loader, sources):
117
- ''' requires host object '''
112
+ """ requires host object """
118
113
  return combine_vars(self.host_groupvars(host, loader, sources), self.host_vars(host, loader, sources))
119
114
 
120
115
  def host_groupvars(self, host, loader, sources):
121
- ''' requires host object '''
116
+ """ requires host object """
122
117
  gvars = get_group_vars(host.get_groups())
123
118
 
124
119
  if self.get_option('use_vars_plugins'):
@@ -127,7 +122,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
127
122
  return gvars
128
123
 
129
124
  def host_vars(self, host, loader, sources):
130
- ''' requires host object '''
125
+ """ requires host object """
131
126
  hvars = host.get_vars()
132
127
 
133
128
  if self.get_option('use_vars_plugins'):
@@ -136,7 +131,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
136
131
  return hvars
137
132
 
138
133
  def parse(self, inventory, loader, path, cache=False):
139
- ''' parses the inventory file '''
134
+ """ parses the inventory file """
140
135
 
141
136
  super(InventoryModule, self).parse(inventory, loader, path, cache=cache)
142
137
 
@@ -147,26 +142,28 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
147
142
  sources = inventory.processed_sources
148
143
  except AttributeError:
149
144
  if self.get_option('use_vars_plugins'):
150
- raise AnsibleOptionsError("The option use_vars_plugins requires ansible >= 2.11.")
145
+ raise
151
146
 
152
147
  strict = self.get_option('strict')
153
- fact_cache = FactCache()
148
+
149
+ cache = cache_loader.get(C.CACHE_PLUGIN)
150
+
154
151
  try:
155
152
  # Go over hosts (less var copies)
156
153
  for host in inventory.hosts:
157
154
 
158
155
  # get available variables to templar
159
156
  hostvars = self.get_all_host_vars(inventory.hosts[host], loader, sources)
160
- if host in fact_cache: # adds facts if cache is active
161
- hostvars = combine_vars(hostvars, fact_cache[host])
157
+ if cache.contains(host): # adds facts if cache is active
158
+ hostvars = combine_vars(hostvars, cache.get(host))
162
159
 
163
160
  # create composite vars
164
161
  self._set_composite_vars(self.get_option('compose'), hostvars, host, strict=strict)
165
162
 
166
163
  # refetch host vars in case new ones have been created above
167
164
  hostvars = self.get_all_host_vars(inventory.hosts[host], loader, sources)
168
- if host in self._cache: # adds facts if cache is active
169
- hostvars = combine_vars(hostvars, self._cache[host])
165
+ if cache.contains(host): # adds facts if cache is active
166
+ hostvars = combine_vars(hostvars, cache.get(host))
170
167
 
171
168
  # constructed groups based on conditionals
172
169
  self._add_host_to_composed_groups(self.get_option('groups'), hostvars, host, strict=strict, fetch_hostvars=False)
@@ -174,5 +171,5 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
174
171
  # constructed groups based variable values
175
172
  self._add_host_to_keyed_groups(self.get_option('keyed_groups'), hostvars, host, strict=strict, fetch_hostvars=False)
176
173
 
177
- except Exception as e:
178
- raise AnsibleParserError("failed to parse %s: %s " % (to_native(path), to_native(e)), orig_exc=e)
174
+ except Exception as ex:
175
+ raise AnsibleParserError(f"Failed to parse {path!r}.") from ex
@@ -3,7 +3,7 @@
3
3
 
4
4
  from __future__ import annotations
5
5
 
6
- DOCUMENTATION = '''
6
+ DOCUMENTATION = """
7
7
  name: generator
8
8
  version_added: "2.6"
9
9
  short_description: Uses Jinja2 to construct hosts and groups from patterns
@@ -32,9 +32,9 @@ DOCUMENTATION = '''
32
32
  description:
33
33
  - A dictionary of layers, with the key being the layer name, used as a variable name in the C(host)
34
34
  C(name) and C(parents) keys. Each layer value is a list of possible values for that layer.
35
- '''
35
+ """
36
36
 
37
- EXAMPLES = '''
37
+ EXAMPLES = """
38
38
  # inventory.config file in YAML format
39
39
  # remember to enable this inventory plugin in the ansible.cfg before using
40
40
  # View the output using `ansible-inventory -i inventory.config --list`
@@ -68,7 +68,7 @@ EXAMPLES = '''
68
68
  application:
69
69
  - web
70
70
  - api
71
- '''
71
+ """
72
72
 
73
73
  import os
74
74
 
@@ -84,6 +84,8 @@ class InventoryModule(BaseInventoryPlugin):
84
84
 
85
85
  NAME = 'generator'
86
86
 
87
+ # implicit trust behavior is already added by the YAML parser invoked by the loader
88
+
87
89
  def __init__(self):
88
90
 
89
91
  super(InventoryModule, self).__init__()
@@ -100,15 +102,18 @@ class InventoryModule(BaseInventoryPlugin):
100
102
  return valid
101
103
 
102
104
  def template(self, pattern, variables):
103
- self.templar.available_variables = variables
104
- return self.templar.do_template(pattern)
105
+ # Allow pass-through of data structures for templating later (if applicable).
106
+ # This limitation was part of the original plugin implementation and was updated to maintain feature parity with the new templating API.
107
+ if not isinstance(pattern, str):
108
+ return pattern
109
+
110
+ return self.templar.copy_with_new_env(available_variables=variables).template(pattern)
105
111
 
106
112
  def add_parents(self, inventory, child, parents, template_vars):
107
113
  for parent in parents:
108
- try:
109
- groupname = self.template(parent['name'], template_vars)
110
- except (AttributeError, ValueError):
111
- raise AnsibleParserError("Element %s has a parent with no name element" % child['name'])
114
+ groupname = self.template(parent.get('name'), template_vars)
115
+ if not groupname:
116
+ raise AnsibleParserError(f"Element {child} has a parent with no name.")
112
117
  if groupname not in inventory.groups:
113
118
  inventory.add_group(groupname)
114
119
  group = inventory.groups[groupname]
@@ -118,7 +123,7 @@ class InventoryModule(BaseInventoryPlugin):
118
123
  self.add_parents(inventory, groupname, parent.get('parents', []), template_vars)
119
124
 
120
125
  def parse(self, inventory, loader, path, cache=False):
121
- ''' parses the inventory file '''
126
+ """ parses the inventory file """
122
127
 
123
128
  super(InventoryModule, self).parse(inventory, loader, path, cache=cache)
124
129