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

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

Potentially problematic release.


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

Files changed (757) hide show
  1. ansible/_internal/__init__.py +53 -0
  2. ansible/_internal/_ansiballz/__init__.py +0 -0
  3. ansible/_internal/_ansiballz/_builder.py +101 -0
  4. ansible/_internal/_ansiballz/_wrapper.py +262 -0
  5. ansible/_internal/_collection_proxy.py +47 -0
  6. ansible/_internal/_datatag/__init__.py +0 -0
  7. ansible/_internal/_datatag/_tags.py +130 -0
  8. ansible/_internal/_datatag/_utils.py +19 -0
  9. ansible/_internal/_datatag/_wrappers.py +33 -0
  10. ansible/_internal/_errors/__init__.py +0 -0
  11. ansible/_internal/_errors/_alarm_timeout.py +66 -0
  12. ansible/_internal/_errors/_captured.py +123 -0
  13. ansible/_internal/_errors/_error_factory.py +89 -0
  14. ansible/_internal/_errors/_error_utils.py +240 -0
  15. ansible/_internal/_errors/_handler.py +91 -0
  16. ansible/_internal/_errors/_task_timeout.py +28 -0
  17. ansible/_internal/_event_formatting.py +127 -0
  18. ansible/_internal/_json/__init__.py +214 -0
  19. ansible/_internal/_json/_legacy_encoder.py +34 -0
  20. ansible/_internal/_json/_profiles/__init__.py +0 -0
  21. ansible/_internal/_json/_profiles/_cache_persistence.py +57 -0
  22. ansible/_internal/_json/_profiles/_inventory_legacy.py +40 -0
  23. ansible/_internal/_json/_profiles/_legacy.py +189 -0
  24. ansible/_internal/_locking.py +21 -0
  25. ansible/_internal/_plugins/__init__.py +0 -0
  26. ansible/_internal/_plugins/_cache.py +57 -0
  27. ansible/_internal/_ssh/__init__.py +0 -0
  28. ansible/_internal/_ssh/_agent_launch.py +91 -0
  29. ansible/_internal/_ssh/_ssh_agent.py +619 -0
  30. ansible/_internal/_task.py +78 -0
  31. ansible/_internal/_templating/__init__.py +12 -0
  32. ansible/_internal/_templating/_access.py +86 -0
  33. ansible/_internal/_templating/_chain_templar.py +63 -0
  34. ansible/_internal/_templating/_datatag.py +95 -0
  35. ansible/_internal/_templating/_engine.py +592 -0
  36. ansible/_internal/_templating/_errors.py +28 -0
  37. ansible/_internal/_templating/_jinja_bits.py +1106 -0
  38. ansible/_internal/_templating/_jinja_common.py +323 -0
  39. ansible/_internal/_templating/_jinja_patches.py +44 -0
  40. ansible/_internal/_templating/_jinja_plugins.py +375 -0
  41. ansible/_internal/_templating/_lazy_containers.py +633 -0
  42. ansible/_internal/_templating/_marker_behaviors.py +103 -0
  43. ansible/_internal/_templating/_template_vars.py +72 -0
  44. ansible/_internal/_templating/_transform.py +70 -0
  45. ansible/_internal/_templating/_utils.py +108 -0
  46. ansible/_internal/_testing.py +26 -0
  47. ansible/_internal/_wrapt.py +1052 -0
  48. ansible/_internal/_yaml/__init__.py +0 -0
  49. ansible/_internal/_yaml/_constructor.py +240 -0
  50. ansible/_internal/_yaml/_dumper.py +70 -0
  51. ansible/_internal/_yaml/_errors.py +166 -0
  52. ansible/_internal/_yaml/_loader.py +66 -0
  53. ansible/_internal/ansible_collections/ansible/_protomatter/README.md +11 -0
  54. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/action/debug.py +36 -0
  55. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/apply_trust.py +19 -0
  56. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/dump_object.py +27 -0
  57. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/finalize.py +16 -0
  58. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/origin.py +18 -0
  59. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/python_literal_eval.py +24 -0
  60. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/python_literal_eval.yml +33 -0
  61. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/tag_names.py +16 -0
  62. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/true_type.py +17 -0
  63. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/unmask.py +49 -0
  64. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/lookup/config.py +21 -0
  65. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/lookup/config.yml +2 -0
  66. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged.py +15 -0
  67. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged.yml +19 -0
  68. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged_with.py +18 -0
  69. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged_with.yml +19 -0
  70. ansible/cli/__init__.py +93 -104
  71. ansible/cli/_ssh_askpass.py +54 -0
  72. ansible/cli/adhoc.py +20 -10
  73. ansible/cli/arguments/option_helpers.py +163 -10
  74. ansible/cli/config.py +43 -68
  75. ansible/cli/console.py +13 -11
  76. ansible/cli/doc.py +134 -77
  77. ansible/cli/galaxy.py +27 -20
  78. ansible/cli/inventory.py +28 -28
  79. ansible/cli/playbook.py +4 -12
  80. ansible/cli/pull.py +6 -3
  81. ansible/cli/scripts/ansible_connection_cli_stub.py +7 -7
  82. ansible/cli/vault.py +12 -11
  83. ansible/compat/__init__.py +2 -2
  84. ansible/compat/importlib_resources.py +9 -12
  85. ansible/config/base.yml +218 -133
  86. ansible/config/manager.py +220 -159
  87. ansible/constants.py +2 -65
  88. ansible/errors/__init__.py +350 -256
  89. ansible/executor/interpreter_discovery.py +28 -149
  90. ansible/executor/module_common.py +480 -514
  91. ansible/executor/play_iterator.py +22 -27
  92. ansible/executor/playbook_executor.py +11 -11
  93. ansible/executor/powershell/async_watchdog.ps1 +97 -102
  94. ansible/executor/powershell/async_wrapper.ps1 +204 -153
  95. ansible/executor/powershell/become_wrapper.ps1 +107 -144
  96. ansible/executor/powershell/bootstrap_wrapper.ps1 +46 -9
  97. ansible/executor/powershell/coverage_wrapper.ps1 +91 -135
  98. ansible/executor/powershell/exec_wrapper.ps1 +675 -196
  99. ansible/executor/powershell/module_manifest.py +469 -265
  100. ansible/executor/powershell/module_wrapper.ps1 +195 -186
  101. ansible/executor/powershell/powershell_expand_user.ps1 +20 -0
  102. ansible/executor/powershell/powershell_mkdtemp.ps1 +17 -0
  103. ansible/executor/powershell/psrp_fetch_file.ps1 +41 -0
  104. ansible/executor/powershell/psrp_put_file.ps1 +122 -0
  105. ansible/executor/powershell/winrm_fetch_file.ps1 +46 -0
  106. ansible/executor/powershell/winrm_put_file.ps1 +36 -0
  107. ansible/executor/process/worker.py +139 -149
  108. ansible/executor/stats.py +5 -5
  109. ansible/executor/task_executor.py +270 -297
  110. ansible/executor/task_queue_manager.py +135 -137
  111. ansible/executor/task_result.py +182 -79
  112. ansible/galaxy/__init__.py +2 -2
  113. ansible/galaxy/api.py +26 -25
  114. ansible/galaxy/collection/__init__.py +6 -14
  115. ansible/galaxy/collection/concrete_artifact_manager.py +12 -21
  116. ansible/galaxy/dependency_resolution/dataclasses.py +14 -4
  117. ansible/galaxy/dependency_resolution/providers.py +4 -4
  118. ansible/galaxy/dependency_resolution/reporters.py +81 -0
  119. ansible/galaxy/role.py +6 -10
  120. ansible/galaxy/token.py +28 -21
  121. ansible/inventory/data.py +47 -57
  122. ansible/inventory/group.py +50 -73
  123. ansible/inventory/helpers.py +9 -0
  124. ansible/inventory/host.py +37 -54
  125. ansible/inventory/manager.py +79 -34
  126. ansible/keyword_desc.yml +1 -1
  127. ansible/module_utils/_internal/__init__.py +55 -0
  128. ansible/module_utils/_internal/_ambient_context.py +58 -0
  129. ansible/module_utils/_internal/_ansiballz/__init__.py +0 -0
  130. ansible/module_utils/_internal/_ansiballz/_extensions/__init__.py +0 -0
  131. ansible/module_utils/_internal/_ansiballz/_extensions/_coverage.py +45 -0
  132. ansible/module_utils/_internal/_ansiballz/_extensions/_pydevd.py +62 -0
  133. ansible/module_utils/_internal/_ansiballz/_loader.py +81 -0
  134. ansible/module_utils/_internal/_ansiballz/_respawn.py +32 -0
  135. ansible/module_utils/_internal/_ansiballz/_respawn_wrapper.py +23 -0
  136. ansible/module_utils/_internal/_concurrent/_daemon_threading.py +1 -0
  137. ansible/module_utils/_internal/_dataclass_validation.py +217 -0
  138. ansible/module_utils/_internal/_datatag/__init__.py +961 -0
  139. ansible/module_utils/_internal/_datatag/_tags.py +16 -0
  140. ansible/module_utils/_internal/_debugging.py +31 -0
  141. ansible/module_utils/_internal/_deprecator.py +157 -0
  142. ansible/module_utils/_internal/_errors.py +101 -0
  143. ansible/module_utils/_internal/_event_utils.py +61 -0
  144. ansible/module_utils/_internal/_json/__init__.py +63 -0
  145. ansible/module_utils/_internal/_json/_legacy_encoder.py +26 -0
  146. ansible/module_utils/_internal/_json/_profiles/__init__.py +428 -0
  147. ansible/module_utils/_internal/_json/_profiles/_fallback_to_str.py +73 -0
  148. ansible/module_utils/_internal/_json/_profiles/_module_legacy_c2m.py +33 -0
  149. ansible/module_utils/_internal/_json/_profiles/_module_legacy_m2c.py +37 -0
  150. ansible/module_utils/_internal/_json/_profiles/_module_modern_c2m.py +35 -0
  151. ansible/module_utils/_internal/_json/_profiles/_module_modern_m2c.py +33 -0
  152. ansible/module_utils/_internal/_json/_profiles/_tagless.py +52 -0
  153. ansible/module_utils/_internal/_messages.py +130 -0
  154. ansible/module_utils/_internal/_patches/__init__.py +66 -0
  155. ansible/module_utils/_internal/_patches/_dataclass_annotation_patch.py +53 -0
  156. ansible/module_utils/_internal/_patches/_socket_patch.py +34 -0
  157. ansible/module_utils/_internal/_patches/_sys_intern_patch.py +34 -0
  158. ansible/module_utils/_internal/_plugin_info.py +38 -0
  159. ansible/module_utils/_internal/_stack.py +22 -0
  160. ansible/module_utils/_internal/_testing.py +0 -0
  161. ansible/module_utils/_internal/_text_utils.py +6 -0
  162. ansible/module_utils/_internal/_traceback.py +92 -0
  163. ansible/module_utils/_internal/_validation.py +14 -0
  164. ansible/module_utils/ansible_release.py +2 -2
  165. ansible/module_utils/api.py +1 -2
  166. ansible/module_utils/basic.py +303 -202
  167. ansible/module_utils/common/_utils.py +24 -28
  168. ansible/module_utils/common/arg_spec.py +8 -3
  169. ansible/module_utils/common/collections.py +7 -2
  170. ansible/module_utils/common/dict_transformations.py +2 -2
  171. ansible/module_utils/common/file.py +2 -2
  172. ansible/module_utils/common/json.py +90 -84
  173. ansible/module_utils/common/locale.py +2 -2
  174. ansible/module_utils/common/parameters.py +27 -24
  175. ansible/module_utils/common/process.py +2 -3
  176. ansible/module_utils/common/respawn.py +11 -33
  177. ansible/module_utils/common/sentinel.py +66 -0
  178. ansible/module_utils/common/sys_info.py +8 -8
  179. ansible/module_utils/common/text/converters.py +16 -37
  180. ansible/module_utils/common/validation.py +35 -24
  181. ansible/module_utils/common/warnings.py +143 -25
  182. ansible/module_utils/common/yaml.py +29 -3
  183. ansible/module_utils/compat/datetime.py +33 -21
  184. ansible/module_utils/compat/paramiko.py +21 -10
  185. ansible/module_utils/compat/typing.py +6 -5
  186. ansible/module_utils/connection.py +10 -13
  187. ansible/module_utils/csharp/Ansible.Basic.cs +15 -12
  188. ansible/module_utils/csharp/Ansible.Become.cs +1 -0
  189. ansible/module_utils/csharp/Ansible.Privilege.cs +2 -2
  190. ansible/module_utils/csharp/Ansible._Async.cs +517 -0
  191. ansible/module_utils/datatag.py +49 -0
  192. ansible/module_utils/distro/__init__.py +2 -2
  193. ansible/module_utils/facts/ansible_collector.py +4 -5
  194. ansible/module_utils/facts/collector.py +13 -14
  195. ansible/module_utils/facts/compat.py +4 -4
  196. ansible/module_utils/facts/default_collectors.py +1 -1
  197. ansible/module_utils/facts/hardware/aix.py +34 -0
  198. ansible/module_utils/facts/hardware/base.py +2 -2
  199. ansible/module_utils/facts/hardware/darwin.py +1 -3
  200. ansible/module_utils/facts/hardware/freebsd.py +2 -2
  201. ansible/module_utils/facts/hardware/linux.py +5 -5
  202. ansible/module_utils/facts/namespace.py +1 -1
  203. ansible/module_utils/facts/network/base.py +1 -1
  204. ansible/module_utils/facts/network/fc_wwn.py +1 -2
  205. ansible/module_utils/facts/network/iscsi.py +1 -2
  206. ansible/module_utils/facts/network/nvme.py +1 -2
  207. ansible/module_utils/facts/other/facter.py +2 -3
  208. ansible/module_utils/facts/other/ohai.py +2 -3
  209. ansible/module_utils/facts/sysctl.py +4 -6
  210. ansible/module_utils/facts/system/apparmor.py +1 -2
  211. ansible/module_utils/facts/system/caps.py +3 -3
  212. ansible/module_utils/facts/system/chroot.py +1 -2
  213. ansible/module_utils/facts/system/cmdline.py +1 -2
  214. ansible/module_utils/facts/system/date_time.py +5 -3
  215. ansible/module_utils/facts/system/distribution.py +27 -13
  216. ansible/module_utils/facts/system/dns.py +1 -1
  217. ansible/module_utils/facts/system/env.py +1 -2
  218. ansible/module_utils/facts/system/fips.py +7 -20
  219. ansible/module_utils/facts/system/loadavg.py +1 -2
  220. ansible/module_utils/facts/system/local.py +2 -3
  221. ansible/module_utils/facts/system/lsb.py +1 -2
  222. ansible/module_utils/facts/system/pkg_mgr.py +1 -2
  223. ansible/module_utils/facts/system/platform.py +1 -2
  224. ansible/module_utils/facts/system/python.py +1 -2
  225. ansible/module_utils/facts/system/selinux.py +1 -1
  226. ansible/module_utils/facts/system/service_mgr.py +1 -2
  227. ansible/module_utils/facts/system/ssh_pub_keys.py +1 -1
  228. ansible/module_utils/facts/system/systemd.py +1 -1
  229. ansible/module_utils/facts/system/user.py +1 -2
  230. ansible/module_utils/facts/utils.py +3 -3
  231. ansible/module_utils/facts/virtual/base.py +1 -1
  232. ansible/module_utils/facts/virtual/linux.py +3 -3
  233. ansible/module_utils/facts/virtual/sunos.py +3 -15
  234. ansible/module_utils/facts/virtual/sysctl.py +3 -16
  235. ansible/module_utils/json_utils.py +2 -2
  236. ansible/module_utils/parsing/convert_bool.py +7 -1
  237. ansible/module_utils/powershell/Ansible.ModuleUtils.AddType.psm1 +1 -1
  238. ansible/module_utils/powershell/Ansible.ModuleUtils.CamelConversion.psm1 +1 -1
  239. ansible/module_utils/powershell/Ansible.ModuleUtils.CommandUtil.psm1 +1 -1
  240. ansible/module_utils/powershell/Ansible.ModuleUtils.WebRequest.psm1 +1 -1
  241. ansible/module_utils/service.py +21 -31
  242. ansible/module_utils/splitter.py +7 -7
  243. ansible/module_utils/testing.py +31 -0
  244. ansible/module_utils/urls.py +64 -35
  245. ansible/modules/add_host.py +4 -4
  246. ansible/modules/apt.py +69 -49
  247. ansible/modules/apt_key.py +19 -12
  248. ansible/modules/apt_repository.py +32 -51
  249. ansible/modules/assemble.py +16 -14
  250. ansible/modules/assert.py +4 -4
  251. ansible/modules/async_status.py +24 -24
  252. ansible/modules/async_wrapper.py +20 -25
  253. ansible/modules/blockinfile.py +6 -7
  254. ansible/modules/command.py +13 -20
  255. ansible/modules/copy.py +60 -147
  256. ansible/modules/cron.py +24 -21
  257. ansible/modules/deb822_repository.py +8 -9
  258. ansible/modules/debconf.py +5 -5
  259. ansible/modules/debug.py +4 -4
  260. ansible/modules/dnf.py +8 -8
  261. ansible/modules/dnf5.py +39 -13
  262. ansible/modules/dpkg_selections.py +4 -4
  263. ansible/modules/expect.py +13 -15
  264. ansible/modules/fail.py +4 -4
  265. ansible/modules/fetch.py +4 -4
  266. ansible/modules/file.py +184 -144
  267. ansible/modules/find.py +22 -20
  268. ansible/modules/gather_facts.py +3 -3
  269. ansible/modules/get_url.py +77 -54
  270. ansible/modules/getent.py +7 -9
  271. ansible/modules/git.py +38 -38
  272. ansible/modules/group.py +6 -6
  273. ansible/modules/group_by.py +4 -4
  274. ansible/modules/hostname.py +15 -32
  275. ansible/modules/import_playbook.py +6 -6
  276. ansible/modules/import_role.py +6 -6
  277. ansible/modules/import_tasks.py +6 -6
  278. ansible/modules/include_role.py +6 -6
  279. ansible/modules/include_tasks.py +6 -6
  280. ansible/modules/include_vars.py +6 -6
  281. ansible/modules/iptables.py +86 -73
  282. ansible/modules/known_hosts.py +22 -24
  283. ansible/modules/lineinfile.py +5 -5
  284. ansible/modules/meta.py +4 -4
  285. ansible/modules/mount_facts.py +2 -2
  286. ansible/modules/package.py +10 -4
  287. ansible/modules/package_facts.py +22 -10
  288. ansible/modules/pause.py +6 -6
  289. ansible/modules/ping.py +6 -6
  290. ansible/modules/pip.py +21 -26
  291. ansible/modules/raw.py +6 -6
  292. ansible/modules/reboot.py +6 -6
  293. ansible/modules/replace.py +10 -14
  294. ansible/modules/rpm_key.py +7 -8
  295. ansible/modules/script.py +4 -4
  296. ansible/modules/service.py +10 -17
  297. ansible/modules/service_facts.py +87 -10
  298. ansible/modules/set_fact.py +5 -5
  299. ansible/modules/set_stats.py +4 -4
  300. ansible/modules/setup.py +2 -2
  301. ansible/modules/shell.py +6 -6
  302. ansible/modules/slurp.py +16 -19
  303. ansible/modules/stat.py +15 -31
  304. ansible/modules/subversion.py +15 -15
  305. ansible/modules/systemd.py +7 -7
  306. ansible/modules/systemd_service.py +7 -7
  307. ansible/modules/sysvinit.py +9 -9
  308. ansible/modules/tempfile.py +5 -6
  309. ansible/modules/template.py +6 -6
  310. ansible/modules/unarchive.py +38 -17
  311. ansible/modules/uri.py +33 -26
  312. ansible/modules/user.py +45 -32
  313. ansible/modules/validate_argument_spec.py +10 -7
  314. ansible/modules/wait_for.py +70 -60
  315. ansible/modules/wait_for_connection.py +6 -6
  316. ansible/modules/yum_repository.py +10 -9
  317. ansible/parsing/ajson.py +17 -37
  318. ansible/parsing/dataloader.py +99 -54
  319. ansible/parsing/mod_args.py +62 -60
  320. ansible/parsing/plugin_docs.py +21 -86
  321. ansible/parsing/quoting.py +1 -1
  322. ansible/parsing/splitter.py +27 -12
  323. ansible/parsing/utils/addresses.py +24 -24
  324. ansible/parsing/utils/jsonify.py +5 -1
  325. ansible/parsing/utils/yaml.py +32 -61
  326. ansible/parsing/vault/__init__.py +327 -99
  327. ansible/parsing/yaml/__init__.py +0 -18
  328. ansible/parsing/yaml/dumper.py +6 -120
  329. ansible/parsing/yaml/loader.py +6 -39
  330. ansible/parsing/yaml/objects.py +43 -335
  331. ansible/playbook/__init__.py +1 -1
  332. ansible/playbook/attribute.py +8 -3
  333. ansible/playbook/base.py +187 -134
  334. ansible/playbook/block.py +26 -24
  335. ansible/playbook/collectionsearch.py +1 -15
  336. ansible/playbook/conditional.py +3 -77
  337. ansible/playbook/handler.py +8 -2
  338. ansible/playbook/helpers.py +41 -53
  339. ansible/playbook/included_file.py +32 -26
  340. ansible/playbook/loop_control.py +2 -2
  341. ansible/playbook/play.py +85 -44
  342. ansible/playbook/play_context.py +14 -17
  343. ansible/playbook/playbook_include.py +27 -62
  344. ansible/playbook/role/__init__.py +64 -49
  345. ansible/playbook/role/definition.py +15 -17
  346. ansible/playbook/role/include.py +2 -4
  347. ansible/playbook/role/metadata.py +10 -11
  348. ansible/playbook/role_include.py +3 -3
  349. ansible/playbook/taggable.py +28 -12
  350. ansible/playbook/task.py +192 -121
  351. ansible/playbook/task_include.py +5 -5
  352. ansible/plugins/__init__.py +58 -26
  353. ansible/plugins/action/__init__.py +188 -186
  354. ansible/plugins/action/add_host.py +2 -2
  355. ansible/plugins/action/assemble.py +11 -18
  356. ansible/plugins/action/assert.py +55 -67
  357. ansible/plugins/action/async_status.py +7 -2
  358. ansible/plugins/action/copy.py +14 -17
  359. ansible/plugins/action/debug.py +37 -31
  360. ansible/plugins/action/dnf.py +3 -4
  361. ansible/plugins/action/fail.py +1 -1
  362. ansible/plugins/action/fetch.py +7 -8
  363. ansible/plugins/action/gather_facts.py +13 -14
  364. ansible/plugins/action/group_by.py +1 -1
  365. ansible/plugins/action/include_vars.py +10 -11
  366. ansible/plugins/action/package.py +8 -14
  367. ansible/plugins/action/pause.py +2 -2
  368. ansible/plugins/action/script.py +27 -38
  369. ansible/plugins/action/service.py +9 -18
  370. ansible/plugins/action/set_fact.py +3 -12
  371. ansible/plugins/action/set_stats.py +3 -8
  372. ansible/plugins/action/template.py +47 -67
  373. ansible/plugins/action/unarchive.py +6 -16
  374. ansible/plugins/action/uri.py +9 -20
  375. ansible/plugins/action/validate_argument_spec.py +5 -5
  376. ansible/plugins/action/wait_for_connection.py +1 -1
  377. ansible/plugins/become/__init__.py +31 -8
  378. ansible/plugins/become/runas.py +71 -0
  379. ansible/plugins/become/su.py +13 -8
  380. ansible/plugins/become/sudo.py +19 -0
  381. ansible/plugins/cache/__init__.py +52 -63
  382. ansible/plugins/cache/base.py +8 -0
  383. ansible/plugins/cache/jsonfile.py +10 -16
  384. ansible/plugins/cache/memory.py +6 -12
  385. ansible/plugins/callback/__init__.py +294 -201
  386. ansible/plugins/callback/default.py +99 -95
  387. ansible/plugins/callback/junit.py +44 -43
  388. ansible/plugins/callback/minimal.py +28 -25
  389. ansible/plugins/callback/oneline.py +34 -21
  390. ansible/plugins/callback/tree.py +27 -16
  391. ansible/plugins/connection/__init__.py +47 -34
  392. ansible/plugins/connection/local.py +156 -60
  393. ansible/plugins/connection/paramiko_ssh.py +34 -24
  394. ansible/plugins/connection/psrp.py +76 -165
  395. ansible/plugins/connection/ssh.py +326 -86
  396. ansible/plugins/connection/winrm.py +62 -141
  397. ansible/plugins/doc_fragments/action_common_attributes.py +14 -14
  398. ansible/plugins/doc_fragments/action_core.py +6 -6
  399. ansible/plugins/doc_fragments/backup.py +2 -2
  400. ansible/plugins/doc_fragments/checksum_common.py +27 -0
  401. ansible/plugins/doc_fragments/constructed.py +8 -4
  402. ansible/plugins/doc_fragments/decrypt.py +2 -2
  403. ansible/plugins/doc_fragments/default_callback.py +2 -2
  404. ansible/plugins/doc_fragments/files.py +2 -2
  405. ansible/plugins/doc_fragments/inventory_cache.py +2 -2
  406. ansible/plugins/doc_fragments/result_format_callback.py +2 -2
  407. ansible/plugins/doc_fragments/return_common.py +2 -2
  408. ansible/plugins/doc_fragments/template_common.py +4 -4
  409. ansible/plugins/doc_fragments/url.py +17 -1
  410. ansible/plugins/doc_fragments/url_windows.py +2 -2
  411. ansible/plugins/doc_fragments/validate.py +2 -2
  412. ansible/plugins/doc_fragments/vars_plugin_staging.py +2 -2
  413. ansible/plugins/filter/__init__.py +6 -2
  414. ansible/plugins/filter/b64decode.yml +22 -0
  415. ansible/plugins/filter/b64encode.yml +22 -0
  416. ansible/plugins/filter/bool.yml +11 -4
  417. ansible/plugins/filter/core.py +245 -120
  418. ansible/plugins/filter/encryption.py +42 -34
  419. ansible/plugins/filter/flatten.yml +3 -2
  420. ansible/plugins/filter/human_to_bytes.yml +1 -1
  421. ansible/plugins/filter/mathstuff.py +30 -37
  422. ansible/plugins/filter/password_hash.yml +8 -0
  423. ansible/plugins/filter/pow.yml +1 -1
  424. ansible/plugins/filter/regex_search.yml +1 -4
  425. ansible/plugins/filter/root.yml +1 -1
  426. ansible/plugins/filter/split.yml +1 -1
  427. ansible/plugins/filter/strftime.yml +3 -3
  428. ansible/plugins/filter/to_nice_yaml.yml +0 -4
  429. ansible/plugins/filter/to_uuid.yml +1 -1
  430. ansible/plugins/filter/to_yaml.yml +0 -4
  431. ansible/plugins/filter/unvault.yml +1 -1
  432. ansible/plugins/filter/urls.py +1 -1
  433. ansible/plugins/filter/urlsplit.py +8 -9
  434. ansible/plugins/filter/vault.yml +14 -9
  435. ansible/plugins/filter/win_basename.yml +6 -1
  436. ansible/plugins/filter/win_dirname.yml +5 -0
  437. ansible/plugins/inventory/__init__.py +107 -86
  438. ansible/plugins/inventory/advanced_host_list.py +7 -5
  439. ansible/plugins/inventory/auto.py +11 -4
  440. ansible/plugins/inventory/constructed.py +21 -24
  441. ansible/plugins/inventory/generator.py +16 -11
  442. ansible/plugins/inventory/host_list.py +7 -5
  443. ansible/plugins/inventory/ini.py +78 -44
  444. ansible/plugins/inventory/script.py +190 -120
  445. ansible/plugins/inventory/toml.py +16 -126
  446. ansible/plugins/inventory/yaml.py +10 -8
  447. ansible/plugins/list.py +72 -19
  448. ansible/plugins/loader.py +383 -198
  449. ansible/plugins/lookup/__init__.py +21 -4
  450. ansible/plugins/lookup/config.py +21 -35
  451. ansible/plugins/lookup/csvfile.py +19 -73
  452. ansible/plugins/lookup/dict.py +1 -6
  453. ansible/plugins/lookup/env.py +12 -9
  454. ansible/plugins/lookup/file.py +5 -8
  455. ansible/plugins/lookup/first_found.py +87 -55
  456. ansible/plugins/lookup/indexed_items.py +1 -10
  457. ansible/plugins/lookup/ini.py +14 -13
  458. ansible/plugins/lookup/items.py +1 -1
  459. ansible/plugins/lookup/lines.py +8 -1
  460. ansible/plugins/lookup/list.py +1 -1
  461. ansible/plugins/lookup/nested.py +2 -18
  462. ansible/plugins/lookup/password.py +5 -5
  463. ansible/plugins/lookup/pipe.py +5 -7
  464. ansible/plugins/lookup/sequence.py +18 -8
  465. ansible/plugins/lookup/subelements.py +1 -4
  466. ansible/plugins/lookup/template.py +47 -36
  467. ansible/plugins/lookup/together.py +0 -12
  468. ansible/plugins/lookup/unvault.py +1 -5
  469. ansible/plugins/lookup/url.py +4 -10
  470. ansible/plugins/lookup/vars.py +16 -24
  471. ansible/plugins/shell/__init__.py +58 -4
  472. ansible/plugins/shell/cmd.py +2 -2
  473. ansible/plugins/shell/powershell.py +106 -31
  474. ansible/plugins/shell/sh.py +13 -7
  475. ansible/plugins/strategy/__init__.py +168 -193
  476. ansible/plugins/strategy/debug.py +2 -2
  477. ansible/plugins/strategy/free.py +16 -31
  478. ansible/plugins/strategy/host_pinned.py +2 -2
  479. ansible/plugins/strategy/linear.py +41 -41
  480. ansible/plugins/terminal/__init__.py +4 -4
  481. ansible/plugins/test/__init__.py +7 -2
  482. ansible/plugins/test/core.py +75 -35
  483. ansible/plugins/test/files.py +1 -1
  484. ansible/plugins/test/finished.yml +1 -1
  485. ansible/plugins/test/mathstuff.py +3 -3
  486. ansible/plugins/test/uri.py +5 -8
  487. ansible/plugins/vars/host_group_vars.py +7 -14
  488. ansible/release.py +2 -2
  489. ansible/template/__init__.py +353 -943
  490. ansible/utils/__init__.py +0 -18
  491. ansible/utils/collection_loader/__init__.py +54 -5
  492. ansible/utils/collection_loader/_collection_config.py +5 -6
  493. ansible/utils/collection_loader/_collection_finder.py +82 -96
  494. ansible/utils/collection_loader/_collection_meta.py +15 -8
  495. ansible/utils/display.py +485 -73
  496. ansible/utils/encrypt.py +27 -19
  497. ansible/utils/fqcn.py +2 -2
  498. ansible/utils/galaxy.py +2 -2
  499. ansible/utils/hashing.py +8 -10
  500. ansible/utils/helpers.py +2 -2
  501. ansible/utils/listify.py +10 -8
  502. ansible/utils/lock.py +2 -2
  503. ansible/utils/path.py +10 -12
  504. ansible/utils/plugin_docs.py +16 -14
  505. ansible/utils/py3compat.py +2 -7
  506. ansible/utils/sentinel.py +4 -62
  507. ansible/utils/singleton.py +2 -0
  508. ansible/utils/ssh_functions.py +6 -2
  509. ansible/utils/unsafe_proxy.py +23 -332
  510. ansible/utils/vars.py +55 -8
  511. ansible/utils/version.py +2 -2
  512. ansible/vars/clean.py +5 -5
  513. ansible/vars/hostvars.py +60 -90
  514. ansible/vars/manager.py +220 -285
  515. ansible/vars/plugins.py +4 -4
  516. ansible/vars/reserved.py +13 -12
  517. {ansible_core-2.18.7.dist-info → ansible_core-2.19.0.dist-info}/METADATA +4 -3
  518. ansible_core-2.19.0.dist-info/RECORD +1097 -0
  519. ansible_core-2.19.0.dist-info/licenses/licenses/BSD-3-Clause.txt +28 -0
  520. ansible_test/_data/completion/docker.txt +7 -7
  521. ansible_test/_data/completion/remote.txt +6 -6
  522. ansible_test/_data/completion/windows.txt +1 -0
  523. ansible_test/_data/requirements/ansible.txt +2 -2
  524. ansible_test/_data/requirements/sanity.ansible-doc.txt +3 -3
  525. ansible_test/_data/requirements/sanity.changelog.txt +2 -2
  526. ansible_test/_data/requirements/sanity.import.plugin.txt +2 -2
  527. ansible_test/_data/requirements/sanity.pep8.txt +1 -1
  528. ansible_test/_data/requirements/sanity.pylint.txt +5 -5
  529. ansible_test/_data/requirements/sanity.validate-modules.txt +2 -2
  530. ansible_test/_data/requirements/sanity.yamllint.txt +1 -1
  531. ansible_test/_data/requirements/units.txt +1 -0
  532. ansible_test/_internal/__init__.py +6 -0
  533. ansible_test/_internal/ansible_util.py +3 -1
  534. ansible_test/_internal/become.py +1 -0
  535. ansible_test/_internal/bootstrap.py +1 -0
  536. ansible_test/_internal/cache.py +1 -0
  537. ansible_test/_internal/cgroup.py +1 -0
  538. ansible_test/_internal/ci/__init__.py +1 -0
  539. ansible_test/_internal/ci/azp.py +1 -0
  540. ansible_test/_internal/ci/local.py +1 -0
  541. ansible_test/_internal/classification/__init__.py +1 -0
  542. ansible_test/_internal/classification/common.py +1 -0
  543. ansible_test/_internal/classification/csharp.py +1 -0
  544. ansible_test/_internal/classification/powershell.py +1 -0
  545. ansible_test/_internal/classification/python.py +1 -0
  546. ansible_test/_internal/cli/__init__.py +1 -0
  547. ansible_test/_internal/cli/actions.py +1 -0
  548. ansible_test/_internal/cli/argparsing/__init__.py +1 -0
  549. ansible_test/_internal/cli/argparsing/actions.py +1 -0
  550. ansible_test/_internal/cli/argparsing/argcompletion.py +1 -0
  551. ansible_test/_internal/cli/argparsing/parsers.py +1 -0
  552. ansible_test/_internal/cli/commands/__init__.py +11 -5
  553. ansible_test/_internal/cli/commands/coverage/__init__.py +1 -0
  554. ansible_test/_internal/cli/commands/coverage/analyze/__init__.py +1 -0
  555. ansible_test/_internal/cli/commands/coverage/analyze/targets/__init__.py +1 -0
  556. ansible_test/_internal/cli/commands/coverage/analyze/targets/combine.py +1 -0
  557. ansible_test/_internal/cli/commands/coverage/analyze/targets/expand.py +1 -0
  558. ansible_test/_internal/cli/commands/coverage/analyze/targets/filter.py +1 -0
  559. ansible_test/_internal/cli/commands/coverage/analyze/targets/generate.py +1 -0
  560. ansible_test/_internal/cli/commands/coverage/analyze/targets/missing.py +1 -0
  561. ansible_test/_internal/cli/commands/coverage/combine.py +1 -0
  562. ansible_test/_internal/cli/commands/coverage/erase.py +1 -0
  563. ansible_test/_internal/cli/commands/coverage/html.py +1 -0
  564. ansible_test/_internal/cli/commands/coverage/report.py +1 -0
  565. ansible_test/_internal/cli/commands/coverage/xml.py +1 -0
  566. ansible_test/_internal/cli/commands/env.py +1 -0
  567. ansible_test/_internal/cli/commands/integration/__init__.py +1 -0
  568. ansible_test/_internal/cli/commands/integration/network.py +1 -0
  569. ansible_test/_internal/cli/commands/integration/posix.py +1 -0
  570. ansible_test/_internal/cli/commands/integration/windows.py +1 -0
  571. ansible_test/_internal/cli/commands/sanity.py +9 -0
  572. ansible_test/_internal/cli/commands/shell.py +1 -0
  573. ansible_test/_internal/cli/commands/units.py +1 -0
  574. ansible_test/_internal/cli/compat.py +1 -0
  575. ansible_test/_internal/cli/completers.py +1 -0
  576. ansible_test/_internal/cli/converters.py +1 -0
  577. ansible_test/_internal/cli/environments.py +52 -5
  578. ansible_test/_internal/cli/epilog.py +1 -0
  579. ansible_test/_internal/cli/parsers/__init__.py +1 -0
  580. ansible_test/_internal/cli/parsers/base_argument_parsers.py +1 -0
  581. ansible_test/_internal/cli/parsers/helpers.py +1 -0
  582. ansible_test/_internal/cli/parsers/host_config_parsers.py +1 -0
  583. ansible_test/_internal/cli/parsers/key_value_parsers.py +1 -0
  584. ansible_test/_internal/cli/parsers/value_parsers.py +1 -0
  585. ansible_test/_internal/commands/__init__.py +1 -0
  586. ansible_test/_internal/commands/coverage/__init__.py +3 -2
  587. ansible_test/_internal/commands/coverage/analyze/__init__.py +1 -0
  588. ansible_test/_internal/commands/coverage/analyze/targets/__init__.py +1 -0
  589. ansible_test/_internal/commands/coverage/analyze/targets/combine.py +1 -0
  590. ansible_test/_internal/commands/coverage/analyze/targets/expand.py +1 -0
  591. ansible_test/_internal/commands/coverage/analyze/targets/filter.py +1 -0
  592. ansible_test/_internal/commands/coverage/analyze/targets/generate.py +1 -0
  593. ansible_test/_internal/commands/coverage/analyze/targets/missing.py +1 -0
  594. ansible_test/_internal/commands/coverage/combine.py +2 -1
  595. ansible_test/_internal/commands/coverage/erase.py +1 -0
  596. ansible_test/_internal/commands/coverage/html.py +1 -0
  597. ansible_test/_internal/commands/coverage/report.py +1 -0
  598. ansible_test/_internal/commands/coverage/xml.py +1 -0
  599. ansible_test/_internal/commands/env/__init__.py +2 -0
  600. ansible_test/_internal/commands/integration/__init__.py +22 -5
  601. ansible_test/_internal/commands/integration/cloud/__init__.py +1 -0
  602. ansible_test/_internal/commands/integration/cloud/acme.py +2 -1
  603. ansible_test/_internal/commands/integration/cloud/aws.py +1 -0
  604. ansible_test/_internal/commands/integration/cloud/azure.py +1 -0
  605. ansible_test/_internal/commands/integration/cloud/cs.py +1 -0
  606. ansible_test/_internal/commands/integration/cloud/digitalocean.py +1 -0
  607. ansible_test/_internal/commands/integration/cloud/galaxy.py +3 -2
  608. ansible_test/_internal/commands/integration/cloud/hcloud.py +1 -0
  609. ansible_test/_internal/commands/integration/cloud/httptester.py +3 -2
  610. ansible_test/_internal/commands/integration/cloud/nios.py +2 -1
  611. ansible_test/_internal/commands/integration/cloud/opennebula.py +1 -0
  612. ansible_test/_internal/commands/integration/cloud/openshift.py +1 -0
  613. ansible_test/_internal/commands/integration/cloud/scaleway.py +1 -0
  614. ansible_test/_internal/commands/integration/cloud/vcenter.py +1 -0
  615. ansible_test/_internal/commands/integration/cloud/vultr.py +1 -0
  616. ansible_test/_internal/commands/integration/coverage.py +8 -2
  617. ansible_test/_internal/commands/integration/filters.py +1 -0
  618. ansible_test/_internal/commands/integration/network.py +1 -0
  619. ansible_test/_internal/commands/integration/posix.py +1 -0
  620. ansible_test/_internal/commands/integration/windows.py +1 -0
  621. ansible_test/_internal/commands/sanity/__init__.py +19 -2
  622. ansible_test/_internal/commands/sanity/ansible_doc.py +1 -0
  623. ansible_test/_internal/commands/sanity/bin_symlinks.py +1 -0
  624. ansible_test/_internal/commands/sanity/compile.py +1 -0
  625. ansible_test/_internal/commands/sanity/ignores.py +1 -0
  626. ansible_test/_internal/commands/sanity/import.py +1 -0
  627. ansible_test/_internal/commands/sanity/integration_aliases.py +12 -0
  628. ansible_test/_internal/commands/sanity/pep8.py +1 -0
  629. ansible_test/_internal/commands/sanity/pslint.py +1 -0
  630. ansible_test/_internal/commands/sanity/pylint.py +25 -26
  631. ansible_test/_internal/commands/sanity/shellcheck.py +1 -0
  632. ansible_test/_internal/commands/sanity/validate_modules.py +1 -0
  633. ansible_test/_internal/commands/sanity/yamllint.py +1 -0
  634. ansible_test/_internal/commands/shell/__init__.py +44 -4
  635. ansible_test/_internal/commands/units/__init__.py +5 -1
  636. ansible_test/_internal/compat/__init__.py +1 -0
  637. ansible_test/_internal/compat/packaging.py +1 -0
  638. ansible_test/_internal/compat/yaml.py +1 -0
  639. ansible_test/_internal/completion.py +1 -0
  640. ansible_test/_internal/config.py +23 -13
  641. ansible_test/_internal/connections.py +1 -0
  642. ansible_test/_internal/constants.py +1 -0
  643. ansible_test/_internal/containers.py +1 -0
  644. ansible_test/_internal/content_config.py +1 -0
  645. ansible_test/_internal/core_ci.py +1 -0
  646. ansible_test/_internal/coverage_util.py +11 -10
  647. ansible_test/_internal/data.py +1 -0
  648. ansible_test/_internal/debugging.py +166 -0
  649. ansible_test/_internal/delegation.py +22 -13
  650. ansible_test/_internal/dev/__init__.py +1 -0
  651. ansible_test/_internal/dev/container_probe.py +1 -0
  652. ansible_test/_internal/diff.py +3 -2
  653. ansible_test/_internal/docker_util.py +2 -1
  654. ansible_test/_internal/encoding.py +1 -0
  655. ansible_test/_internal/executor.py +1 -0
  656. ansible_test/_internal/git.py +1 -0
  657. ansible_test/_internal/host_configs.py +1 -0
  658. ansible_test/_internal/host_profiles.py +260 -16
  659. ansible_test/_internal/http.py +1 -0
  660. ansible_test/_internal/init.py +1 -0
  661. ansible_test/_internal/inventory.py +39 -3
  662. ansible_test/_internal/io.py +1 -0
  663. ansible_test/_internal/metadata.py +95 -4
  664. ansible_test/_internal/payload.py +1 -0
  665. ansible_test/_internal/processes.py +80 -0
  666. ansible_test/_internal/provider/__init__.py +1 -0
  667. ansible_test/_internal/provider/layout/__init__.py +1 -0
  668. ansible_test/_internal/provider/layout/ansible.py +1 -0
  669. ansible_test/_internal/provider/layout/collection.py +1 -0
  670. ansible_test/_internal/provider/layout/unsupported.py +1 -0
  671. ansible_test/_internal/provider/source/__init__.py +1 -0
  672. ansible_test/_internal/provider/source/git.py +1 -0
  673. ansible_test/_internal/provider/source/installed.py +1 -0
  674. ansible_test/_internal/provider/source/unsupported.py +1 -0
  675. ansible_test/_internal/provider/source/unversioned.py +1 -0
  676. ansible_test/_internal/provisioning.py +11 -4
  677. ansible_test/_internal/pypi_proxy.py +6 -5
  678. ansible_test/_internal/python_requirements.py +28 -0
  679. ansible_test/_internal/ssh.py +2 -5
  680. ansible_test/_internal/target.py +9 -0
  681. ansible_test/_internal/test.py +3 -2
  682. ansible_test/_internal/thread.py +3 -1
  683. ansible_test/_internal/timeout.py +2 -1
  684. ansible_test/_internal/util.py +41 -12
  685. ansible_test/_internal/util_common.py +18 -5
  686. ansible_test/_internal/venv.py +1 -0
  687. ansible_test/_util/controller/sanity/code-smell/action-plugin-docs.py +1 -0
  688. ansible_test/_util/controller/sanity/code-smell/changelog/sphinx.py +1 -0
  689. ansible_test/_util/controller/sanity/code-smell/changelog.py +1 -0
  690. ansible_test/_util/controller/sanity/code-smell/empty-init.py +1 -0
  691. ansible_test/_util/controller/sanity/code-smell/line-endings.py +1 -0
  692. ansible_test/_util/controller/sanity/code-smell/no-assert.py +1 -0
  693. ansible_test/_util/controller/sanity/code-smell/no-get-exception.py +1 -0
  694. ansible_test/_util/controller/sanity/code-smell/no-illegal-filenames.py +1 -0
  695. ansible_test/_util/controller/sanity/code-smell/no-smart-quotes.py +1 -0
  696. ansible_test/_util/controller/sanity/code-smell/replace-urlopen.py +1 -0
  697. ansible_test/_util/controller/sanity/code-smell/runtime-metadata.py +28 -1
  698. ansible_test/_util/controller/sanity/code-smell/shebang.py +1 -0
  699. ansible_test/_util/controller/sanity/code-smell/symlinks.py +1 -0
  700. ansible_test/_util/controller/sanity/code-smell/use-argspec-type-path.py +1 -0
  701. ansible_test/_util/controller/sanity/code-smell/use-compat-six.py +1 -0
  702. ansible_test/_util/controller/sanity/integration-aliases/yaml_to_json.py +2 -1
  703. ansible_test/_util/controller/sanity/pep8/current-ignore.txt +4 -0
  704. ansible_test/_util/controller/sanity/pylint/config/ansible-test-target.cfg +8 -5
  705. ansible_test/_util/controller/sanity/pylint/config/ansible-test.cfg +8 -5
  706. ansible_test/_util/controller/sanity/pylint/config/code-smell.cfg +8 -5
  707. ansible_test/_util/controller/sanity/pylint/config/collection.cfg +4 -5
  708. ansible_test/_util/controller/sanity/pylint/config/default.cfg +8 -7
  709. ansible_test/_util/controller/sanity/pylint/plugins/deprecated_calls.py +541 -0
  710. ansible_test/_util/controller/sanity/pylint/plugins/deprecated_comment.py +137 -0
  711. ansible_test/_util/controller/sanity/pylint/plugins/hide_unraisable.py +1 -0
  712. ansible_test/_util/controller/sanity/pylint/plugins/string_format.py +1 -8
  713. ansible_test/_util/controller/sanity/pylint/plugins/unwanted.py +1 -8
  714. ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py +55 -28
  715. ansible_test/_util/controller/sanity/validate-modules/validate_modules/module_args.py +12 -5
  716. ansible_test/_util/controller/sanity/validate-modules/validate_modules/schema.py +13 -2
  717. ansible_test/_util/controller/sanity/validate-modules/validate_modules/utils.py +1 -0
  718. ansible_test/_util/controller/sanity/yamllint/yamllinter.py +35 -17
  719. ansible_test/_util/controller/tools/collection_detail.py +1 -0
  720. ansible_test/_util/controller/tools/yaml_to_json.py +2 -1
  721. ansible_test/_util/target/injector/python.py +8 -0
  722. ansible_test/_util/target/pytest/plugins/ansible_forked.py +6 -1
  723. ansible_test/_util/target/pytest/plugins/ansible_pytest_collections.py +2 -1
  724. ansible_test/_util/target/pytest/plugins/ansible_pytest_coverage.py +1 -0
  725. ansible_test/_util/target/sanity/compile/compile.py +1 -0
  726. ansible_test/_util/target/sanity/import/importer.py +15 -16
  727. ansible_test/_util/target/setup/bootstrap.sh +9 -20
  728. ansible_test/_util/target/setup/probe_cgroups.py +1 -0
  729. ansible_test/_util/target/setup/quiet_pip.py +1 -0
  730. ansible_test/_util/target/setup/requirements.py +38 -36
  731. ansible_test/_util/target/tools/virtualenvcheck.py +2 -1
  732. ansible_test/_util/target/tools/yamlcheck.py +2 -1
  733. ansible/compat/selectors.py +0 -32
  734. ansible/errors/yaml_strings.py +0 -138
  735. ansible/executor/action_write_locks.py +0 -44
  736. ansible/executor/discovery/python_target.py +0 -47
  737. ansible/executor/powershell/module_powershell_wrapper.ps1 +0 -86
  738. ansible/executor/powershell/module_script_wrapper.ps1 +0 -22
  739. ansible/module_utils/compat/importlib.py +0 -26
  740. ansible/module_utils/compat/selectors.py +0 -32
  741. ansible/module_utils/pycompat24.py +0 -73
  742. ansible/parsing/yaml/constructor.py +0 -178
  743. ansible/template/native_helpers.py +0 -251
  744. ansible/template/template.py +0 -43
  745. ansible/template/vars.py +0 -77
  746. ansible/utils/native_jinja.py +0 -11
  747. ansible/vars/fact_cache.py +0 -71
  748. ansible_core-2.18.7.dist-info/RECORD +0 -992
  749. ansible_test/_util/controller/sanity/pylint/plugins/deprecated.py +0 -411
  750. {ansible_core-2.18.7.dist-info → ansible_core-2.19.0.dist-info}/WHEEL +0 -0
  751. {ansible_core-2.18.7.dist-info → ansible_core-2.19.0.dist-info}/entry_points.txt +0 -0
  752. {ansible_core-2.18.7.dist-info → ansible_core-2.19.0.dist-info}/licenses/COPYING +0 -0
  753. {ansible_core-2.18.7.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/Apache-License.txt +0 -0
  754. {ansible_core-2.18.7.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/MIT-license.txt +0 -0
  755. {ansible_core-2.18.7.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/PSF-license.txt +0 -0
  756. {ansible_core-2.18.7.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/simplified_bsd.txt +0 -0
  757. {ansible_core-2.18.7.dist-info → ansible_core-2.19.0.dist-info}/top_level.txt +0 -0
@@ -1,9 +1,13 @@
1
1
  """Profiles to represent individual test hosts or a user-provided inventory file."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  import abc
5
6
  import dataclasses
7
+ import importlib
8
+ import json
6
9
  import os
10
+ import pathlib
7
11
  import shlex
8
12
  import tempfile
9
13
  import time
@@ -57,6 +61,9 @@ from .util import (
57
61
  HostConnectionError,
58
62
  ANSIBLE_TEST_TARGET_ROOT,
59
63
  WINDOWS_CONNECTION_VARIABLES,
64
+ ANSIBLE_SOURCE_ROOT,
65
+ ANSIBLE_LIB_ROOT,
66
+ ANSIBLE_TEST_ROOT,
60
67
  )
61
68
 
62
69
  from .util_common import (
@@ -91,6 +98,8 @@ from .venv import (
91
98
 
92
99
  from .ssh import (
93
100
  SshConnectionDetail,
101
+ create_ssh_port_forwards,
102
+ SshProcess,
94
103
  )
95
104
 
96
105
  from .ansible_util import (
@@ -205,7 +214,7 @@ class Inventory:
205
214
  inventory_text += f'[{group}]\n'
206
215
 
207
216
  for host, variables in hosts.items():
208
- kvp = ' '.join(f'{key}="{value}"' for key, value in variables.items())
217
+ kvp = ' '.join(f"{key}={value!r}" for key, value in variables.items())
209
218
  inventory_text += f'{host} {kvp}\n'
210
219
 
211
220
  inventory_text += '\n'
@@ -234,18 +243,24 @@ class HostProfile(t.Generic[THostConfig], metaclass=abc.ABCMeta):
234
243
  *,
235
244
  args: EnvironmentConfig,
236
245
  config: THostConfig,
237
- targets: t.Optional[list[HostConfig]],
246
+ controller: ControllerHostProfile,
238
247
  ) -> None:
239
248
  self.args = args
240
249
  self.config = config
241
- self.controller = bool(targets)
242
- self.targets = targets or []
250
+ self.controller = not controller # this profile is a controller whenever the `controller` arg was not provided
251
+ self.targets = args.targets if self.controller else [] # only keep targets if this profile is a controller
252
+ self.controller_profile = controller if isinstance(self, ControllerProfile) else None
243
253
 
244
254
  self.state: dict[str, t.Any] = {}
245
255
  """State that must be persisted across delegation."""
246
256
  self.cache: dict[str, t.Any] = {}
247
257
  """Cache that must not be persisted across delegation."""
248
258
 
259
+ @property
260
+ @abc.abstractmethod
261
+ def name(self) -> str:
262
+ """The name of the host profile."""
263
+
249
264
  def provision(self) -> None:
250
265
  """Provision the host before delegation."""
251
266
 
@@ -273,6 +288,179 @@ class HostProfile(t.Generic[THostConfig], metaclass=abc.ABCMeta):
273
288
  # args will be populated after the instances are restored
274
289
  self.cache = {}
275
290
 
291
+ def __str__(self) -> str:
292
+ return f'{self.__class__.__name__}: {self.name}'
293
+
294
+
295
+ class DebuggableProfile(HostProfile[THostConfig], metaclass=abc.ABCMeta):
296
+ """Base class for profiles remote debugging."""
297
+
298
+ __PYDEVD_PORT_KEY = 'pydevd_port'
299
+ __DEBUGGING_FORWARDER_KEY = 'debugging_forwarder'
300
+
301
+ @property
302
+ def debugging_enabled(self) -> bool:
303
+ """Returns `True` if debugging is enabled for this profile, otherwise `False`."""
304
+ if self.controller:
305
+ return self.args.metadata.debugger_flags.enable
306
+
307
+ return self.args.metadata.debugger_flags.ansiballz
308
+
309
+ @property
310
+ def pydevd_port(self) -> int:
311
+ """The pydevd port to use."""
312
+ return self.state.get(self.__PYDEVD_PORT_KEY) or self.origin_pydev_port
313
+
314
+ @property
315
+ def debugging_forwarder(self) -> SshProcess | None:
316
+ """The SSH forwarding process, if enabled."""
317
+ return self.cache.get(self.__DEBUGGING_FORWARDER_KEY)
318
+
319
+ @debugging_forwarder.setter
320
+ def debugging_forwarder(self, value: SshProcess) -> None:
321
+ """The SSH forwarding process, if enabled."""
322
+ self.cache[self.__DEBUGGING_FORWARDER_KEY] = value
323
+
324
+ @property
325
+ def origin_pydev_port(self) -> int:
326
+ """The pydevd port on the origin."""
327
+ return self.args.metadata.debugger_settings.port
328
+
329
+ def enable_debugger_forwarding(self, ssh: SshConnectionDetail) -> None:
330
+ """Enable pydevd port forwarding from the origin."""
331
+ if not self.debugging_enabled:
332
+ return
333
+
334
+ endpoint = ('localhost', self.origin_pydev_port)
335
+ forwards = [endpoint]
336
+
337
+ self.debugging_forwarder = create_ssh_port_forwards(self.args, ssh, forwards)
338
+
339
+ port_forwards = self.debugging_forwarder.collect_port_forwards()
340
+
341
+ self.state[self.__PYDEVD_PORT_KEY] = port = port_forwards[endpoint]
342
+
343
+ display.info(f'Remote debugging of {self.name!r} is available on port {port}.', verbosity=1)
344
+
345
+ def deprovision(self) -> None:
346
+ """Deprovision the host after delegation has completed."""
347
+ super().deprovision()
348
+
349
+ if not self.debugging_forwarder:
350
+ return # forwarding not in use
351
+
352
+ self.debugging_forwarder.terminate()
353
+
354
+ display.info(f'Waiting for the {self.name!r} remote debugging SSH port forwarding process to terminate.', verbosity=1)
355
+
356
+ self.debugging_forwarder.wait()
357
+
358
+ def get_pydevd_settrace_arguments(self) -> dict[str, object]:
359
+ """Get settrace arguments for pydevd."""
360
+ return self.args.metadata.debugger_settings.settrace | dict(
361
+ host="localhost",
362
+ port=self.pydevd_port,
363
+ )
364
+
365
+ def get_pydevd_environment_variables(self) -> dict[str, str]:
366
+ """Get environment variables needed to configure pydevd for debugging."""
367
+ return dict(
368
+ PATHS_FROM_ECLIPSE_TO_PYTHON=json.dumps(list(self.get_source_mapping().items())),
369
+ )
370
+
371
+ def get_source_mapping(self) -> dict[str, str]:
372
+ """Get the source mapping from the given metadata."""
373
+ from . import data_context
374
+
375
+ if collection := data_context().content.collection:
376
+ source_mapping = {
377
+ f"{self.args.metadata.ansible_test_root}/": f'{ANSIBLE_TEST_ROOT}/',
378
+ f"{self.args.metadata.ansible_lib_root}/": f'{ANSIBLE_LIB_ROOT}/',
379
+ f'{self.args.metadata.collection_root}/ansible_collections/': f'{collection.root}/ansible_collections/',
380
+ }
381
+ else:
382
+ ansible_source_root = pathlib.Path(self.args.metadata.ansible_lib_root).parent.parent
383
+
384
+ source_mapping = {
385
+ f"{ansible_source_root}/": f'{ANSIBLE_SOURCE_ROOT}/',
386
+ }
387
+
388
+ source_mapping = {key: value for key, value in source_mapping.items() if key != value}
389
+
390
+ return source_mapping
391
+
392
+ def activate_debugger(self) -> None:
393
+ """Activate the debugger after delegation."""
394
+ if not self.args.metadata.loaded or not self.args.metadata.debugger_flags.self:
395
+ return
396
+
397
+ display.info('Activating remote debugging of ansible-test.', verbosity=1)
398
+
399
+ os.environ.update(self.get_pydevd_environment_variables())
400
+
401
+ debugging_module = importlib.import_module(self.args.metadata.debugger_settings.module)
402
+ debugging_module.settrace(**self.get_pydevd_settrace_arguments())
403
+
404
+ pass # pylint: disable=unnecessary-pass # when suspend is True, execution pauses here -- it's also a convenient place to put a breakpoint
405
+
406
+ def get_ansiballz_inventory_variables(self) -> dict[str, t.Any]:
407
+ """
408
+ Return inventory variables for remote debugging of AnsiballZ modules.
409
+ When delegating, this function must be called after delegation.
410
+ """
411
+ if not self.args.metadata.debugger_flags.ansiballz:
412
+ return {}
413
+
414
+ return dict(
415
+ _ansible_ansiballz_debugger_config=json.dumps(self.get_ansiballz_debugger_config()),
416
+ )
417
+
418
+ def get_ansiballz_environment_variables(self) -> dict[str, t.Any]:
419
+ """
420
+ Return environment variables for remote debugging of AnsiballZ modules.
421
+ When delegating, this function must be called after delegation.
422
+ """
423
+ if not self.args.metadata.debugger_flags.ansiballz:
424
+ return {}
425
+
426
+ return dict(
427
+ _ANSIBLE_ANSIBALLZ_DEBUGGER_CONFIG=json.dumps(self.get_ansiballz_debugger_config()),
428
+ )
429
+
430
+ def get_ansiballz_debugger_config(self) -> dict[str, t.Any]:
431
+ """
432
+ Return config for remote debugging of AnsiballZ modules.
433
+ When delegating, this function must be called after delegation.
434
+ """
435
+ debugger_config = dict(
436
+ module=self.args.metadata.debugger_settings.module,
437
+ settrace=self.get_pydevd_settrace_arguments(),
438
+ source_mapping=self.get_source_mapping(),
439
+ )
440
+
441
+ display.info(f'>>> Debugger Config ({self.name} AnsiballZ)\n{json.dumps(debugger_config, indent=4)}', verbosity=3)
442
+
443
+ return debugger_config
444
+
445
+ def get_ansible_cli_environment_variables(self) -> dict[str, t.Any]:
446
+ """
447
+ Return environment variables for remote debugging of the Ansible CLI.
448
+ When delegating, this function must be called after delegation.
449
+ """
450
+ if not self.args.metadata.debugger_flags.cli:
451
+ return {}
452
+
453
+ debugger_config = dict(
454
+ args=['-m', 'pydevd', '--client', 'localhost', '--port', str(self.pydevd_port)] + self.args.metadata.debugger_settings.args + ['--file'],
455
+ env=self.get_pydevd_environment_variables(),
456
+ )
457
+
458
+ display.info(f'>>> Debugger Config ({self.name} Ansible CLI)\n{json.dumps(debugger_config, indent=4)}', verbosity=3)
459
+
460
+ return dict(
461
+ ANSIBLE_TEST_DEBUGGER_CONFIG=json.dumps(debugger_config),
462
+ )
463
+
276
464
 
277
465
  class PosixProfile(HostProfile[TPosixConfig], metaclass=abc.ABCMeta):
278
466
  """Base class for POSIX host profiles."""
@@ -296,7 +484,7 @@ class PosixProfile(HostProfile[TPosixConfig], metaclass=abc.ABCMeta):
296
484
  return python
297
485
 
298
486
 
299
- class ControllerHostProfile(PosixProfile[TControllerHostConfig], metaclass=abc.ABCMeta):
487
+ class ControllerHostProfile(PosixProfile[TControllerHostConfig], DebuggableProfile[TControllerHostConfig], metaclass=abc.ABCMeta):
300
488
  """Base class for profiles usable as a controller."""
301
489
 
302
490
  @abc.abstractmethod
@@ -319,6 +507,11 @@ class SshTargetHostProfile(HostProfile[THostConfig], metaclass=abc.ABCMeta):
319
507
  class RemoteProfile(SshTargetHostProfile[TRemoteConfig], metaclass=abc.ABCMeta):
320
508
  """Base class for remote instance profiles."""
321
509
 
510
+ @property
511
+ def name(self) -> str:
512
+ """The name of the host profile."""
513
+ return self.config.name
514
+
322
515
  @property
323
516
  def core_ci_state(self) -> t.Optional[dict[str, str]]:
324
517
  """The saved Ansible Core CI state."""
@@ -338,6 +531,8 @@ class RemoteProfile(SshTargetHostProfile[TRemoteConfig], metaclass=abc.ABCMeta):
338
531
 
339
532
  def deprovision(self) -> None:
340
533
  """Deprovision the host after delegation has completed."""
534
+ super().deprovision()
535
+
341
536
  if self.args.remote_terminate == TerminateMode.ALWAYS or (self.args.remote_terminate == TerminateMode.SUCCESS and self.args.success):
342
537
  self.delete_instance()
343
538
 
@@ -393,9 +588,19 @@ class RemoteProfile(SshTargetHostProfile[TRemoteConfig], metaclass=abc.ABCMeta):
393
588
  )
394
589
 
395
590
 
396
- class ControllerProfile(SshTargetHostProfile[ControllerConfig], PosixProfile[ControllerConfig]):
591
+ class ControllerProfile(SshTargetHostProfile[ControllerConfig], PosixProfile[ControllerConfig], DebuggableProfile[ControllerConfig]):
397
592
  """Host profile for the controller as a target."""
398
593
 
594
+ @property
595
+ def name(self) -> str:
596
+ """The name of the host profile."""
597
+ return self.controller_profile.name
598
+
599
+ @property
600
+ def pydevd_port(self) -> int:
601
+ """The pydevd port to use."""
602
+ return self.controller_profile.pydevd_port
603
+
399
604
  def get_controller_target_connections(self) -> list[SshConnection]:
400
605
  """Return SSH connection(s) for accessing the host as a target from the controller."""
401
606
  settings = SshConnectionDetail(
@@ -410,7 +615,7 @@ class ControllerProfile(SshTargetHostProfile[ControllerConfig], PosixProfile[Con
410
615
  return [SshConnection(self.args, settings)]
411
616
 
412
617
 
413
- class DockerProfile(ControllerHostProfile[DockerConfig], SshTargetHostProfile[DockerConfig]):
618
+ class DockerProfile(ControllerHostProfile[DockerConfig], SshTargetHostProfile[DockerConfig], DebuggableProfile[DockerConfig]):
414
619
  """Host profile for a docker instance."""
415
620
 
416
621
  MARKER = 'ansible-test-marker'
@@ -424,6 +629,11 @@ class DockerProfile(ControllerHostProfile[DockerConfig], SshTargetHostProfile[Do
424
629
  command_privileged: bool
425
630
  expected_mounts: tuple[CGroupMount, ...]
426
631
 
632
+ @property
633
+ def name(self) -> str:
634
+ """The name of the host profile."""
635
+ return self.config.name
636
+
427
637
  @property
428
638
  def container_name(self) -> t.Optional[str]:
429
639
  """Return the stored container name, if any, otherwise None."""
@@ -460,7 +670,7 @@ class DockerProfile(ControllerHostProfile[DockerConfig], SshTargetHostProfile[Do
460
670
  image=self.config.image,
461
671
  name=f'ansible-test-{self.label}',
462
672
  ports=[22],
463
- publish_ports=not self.controller, # connections to the controller over SSH are not required
673
+ publish_ports=self.debugging_enabled or not self.controller, # SSH to the controller is not required unless remote debugging is enabled
464
674
  options=init_config.options,
465
675
  cleanup=False,
466
676
  cmd=self.build_init_command(init_config, init_probe),
@@ -600,7 +810,7 @@ class DockerProfile(ControllerHostProfile[DockerConfig], SshTargetHostProfile[Do
600
810
  # The host namespace must be used to permit the container to access the cgroup v1 systemd hierarchy created by Podman.
601
811
  '--cgroupns', 'host',
602
812
  # Mask the host cgroup tmpfs mount to avoid exposing the host cgroup v1 hierarchies (or cgroup v2 hybrid) to the container.
603
- # Podman will provide a cgroup v1 systemd hiearchy on top of this.
813
+ # Podman will provide a cgroup v1 systemd hierarchy on top of this.
604
814
  '--tmpfs', '/sys/fs/cgroup',
605
815
  ))
606
816
 
@@ -973,8 +1183,13 @@ class DockerProfile(ControllerHostProfile[DockerConfig], SshTargetHostProfile[Do
973
1183
  docker_logs(self.args, self.container_name)
974
1184
  raise
975
1185
 
1186
+ if self.debugging_enabled:
1187
+ self.enable_debugger_forwarding(self.get_ssh_connection_detail(HostType.origin))
1188
+
976
1189
  def deprovision(self) -> None:
977
1190
  """Deprovision the host after delegation has completed."""
1191
+ super().deprovision()
1192
+
978
1193
  container_exists = False
979
1194
 
980
1195
  if self.container_name:
@@ -1024,10 +1239,10 @@ class DockerProfile(ControllerHostProfile[DockerConfig], SshTargetHostProfile[Do
1024
1239
 
1025
1240
  raise HostConnectionError(f'Timeout waiting for {self.config.name} container {self.container_name}.', callback)
1026
1241
 
1027
- def get_controller_target_connections(self) -> list[SshConnection]:
1028
- """Return SSH connection(s) for accessing the host as a target from the controller."""
1242
+ def get_ssh_connection_detail(self, host_type: str) -> SshConnectionDetail:
1243
+ """Return SSH connection detail for the specified host type."""
1029
1244
  containers = get_container_database(self.args)
1030
- access = containers.data[HostType.control]['__test_hosts__'][self.container_name]
1245
+ access = containers.data[host_type]['__test_hosts__'][self.container_name]
1031
1246
 
1032
1247
  host = access.host_ip
1033
1248
  port = dict(access.port_map())[22]
@@ -1045,7 +1260,11 @@ class DockerProfile(ControllerHostProfile[DockerConfig], SshTargetHostProfile[Do
1045
1260
  enable_rsa_sha1='centos6' in self.config.image,
1046
1261
  )
1047
1262
 
1048
- return [SshConnection(self.args, settings)]
1263
+ return settings
1264
+
1265
+ def get_controller_target_connections(self) -> list[SshConnection]:
1266
+ """Return SSH connection(s) for accessing the host as a target from the controller."""
1267
+ return [SshConnection(self.args, self.get_ssh_connection_detail(HostType.control))]
1049
1268
 
1050
1269
  def get_origin_controller_connection(self) -> DockerConnection:
1051
1270
  """Return a connection for accessing the host as a controller from the origin."""
@@ -1115,6 +1334,11 @@ class DockerProfile(ControllerHostProfile[DockerConfig], SshTargetHostProfile[Do
1115
1334
  class NetworkInventoryProfile(HostProfile[NetworkInventoryConfig]):
1116
1335
  """Host profile for a network inventory."""
1117
1336
 
1337
+ @property
1338
+ def name(self) -> str:
1339
+ """The name of the host profile."""
1340
+ return self.config.path
1341
+
1118
1342
 
1119
1343
  class NetworkRemoteProfile(RemoteProfile[NetworkRemoteConfig]):
1120
1344
  """Host profile for a network remote instance."""
@@ -1196,6 +1420,11 @@ class NetworkRemoteProfile(RemoteProfile[NetworkRemoteConfig]):
1196
1420
  class OriginProfile(ControllerHostProfile[OriginConfig]):
1197
1421
  """Host profile for origin."""
1198
1422
 
1423
+ @property
1424
+ def name(self) -> str:
1425
+ """The name of the host profile."""
1426
+ return 'origin'
1427
+
1199
1428
  def get_origin_controller_connection(self) -> LocalConnection:
1200
1429
  """Return a connection for accessing the host as a controller from the origin."""
1201
1430
  return LocalConnection(self.args)
@@ -1205,13 +1434,18 @@ class OriginProfile(ControllerHostProfile[OriginConfig]):
1205
1434
  return os.getcwd()
1206
1435
 
1207
1436
 
1208
- class PosixRemoteProfile(ControllerHostProfile[PosixRemoteConfig], RemoteProfile[PosixRemoteConfig]):
1437
+ class PosixRemoteProfile(ControllerHostProfile[PosixRemoteConfig], RemoteProfile[PosixRemoteConfig], DebuggableProfile[PosixRemoteConfig]):
1209
1438
  """Host profile for a POSIX remote instance."""
1210
1439
 
1211
1440
  def wait(self) -> None:
1212
1441
  """Wait for the instance to be ready. Executed before delegation for the controller and after delegation for targets."""
1213
1442
  self.wait_until_ready()
1214
1443
 
1444
+ def setup(self) -> None:
1445
+ """Perform out-of-band setup before delegation."""
1446
+ if self.debugging_enabled:
1447
+ self.enable_debugger_forwarding(self.get_origin_controller_connection().settings)
1448
+
1215
1449
  def configure(self) -> None:
1216
1450
  """Perform in-band configuration. Executed before delegation for the controller and after delegation for targets."""
1217
1451
  # a target uses a single python version, but a controller may include additional versions for targets running on the controller
@@ -1316,6 +1550,11 @@ class PosixRemoteProfile(ControllerHostProfile[PosixRemoteConfig], RemoteProfile
1316
1550
  class PosixSshProfile(SshTargetHostProfile[PosixSshConfig], PosixProfile[PosixSshConfig]):
1317
1551
  """Host profile for a POSIX SSH instance."""
1318
1552
 
1553
+ @property
1554
+ def name(self) -> str:
1555
+ """The name of the host profile."""
1556
+ return self.config.host
1557
+
1319
1558
  def get_controller_target_connections(self) -> list[SshConnection]:
1320
1559
  """Return SSH connection(s) for accessing the host as a target from the controller."""
1321
1560
  settings = SshConnectionDetail(
@@ -1333,6 +1572,11 @@ class PosixSshProfile(SshTargetHostProfile[PosixSshConfig], PosixProfile[PosixSs
1333
1572
  class WindowsInventoryProfile(SshTargetHostProfile[WindowsInventoryConfig]):
1334
1573
  """Host profile for a Windows inventory."""
1335
1574
 
1575
+ @property
1576
+ def name(self) -> str:
1577
+ """The name of the host profile."""
1578
+ return self.config.path
1579
+
1336
1580
  def get_controller_target_connections(self) -> list[SshConnection]:
1337
1581
  """Return SSH connection(s) for accessing the host as a target from the controller."""
1338
1582
  inventory = parse_inventory(self.args, self.config.path)
@@ -1435,9 +1679,9 @@ def get_config_profile_type_map() -> dict[t.Type[HostConfig], t.Type[HostProfile
1435
1679
  def create_host_profile(
1436
1680
  args: EnvironmentConfig,
1437
1681
  config: HostConfig,
1438
- controller: bool,
1682
+ controller: ControllerHostProfile | None,
1439
1683
  ) -> HostProfile:
1440
1684
  """Create and return a host profile from the given host configuration."""
1441
1685
  profile_type = get_config_profile_type_map()[type(config)]
1442
- profile = profile_type(args=args, config=config, targets=args.targets if controller else None)
1686
+ profile = profile_type(args=args, config=config, controller=controller)
1443
1687
  return profile
@@ -1,4 +1,5 @@
1
1
  """A simple HTTP client."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  import http.client
@@ -1,4 +1,5 @@
1
1
  """Early initialization for ansible-test before most other imports have been performed."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  import resource
@@ -1,7 +1,9 @@
1
1
  """Inventory creation from host profiles."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  import shutil
6
+ import sys
5
7
  import typing as t
6
8
 
7
9
  from .config import (
@@ -13,6 +15,11 @@ from .util import (
13
15
  exclude_none_values,
14
16
  )
15
17
 
18
+ from .host_configs import (
19
+ ControllerConfig,
20
+ PosixRemoteConfig,
21
+ )
22
+
16
23
  from .host_profiles import (
17
24
  ControllerHostProfile,
18
25
  ControllerProfile,
@@ -23,6 +30,7 @@ from .host_profiles import (
23
30
  SshTargetHostProfile,
24
31
  WindowsInventoryProfile,
25
32
  WindowsRemoteProfile,
33
+ DebuggableProfile,
26
34
  )
27
35
 
28
36
  from .ssh import (
@@ -30,12 +38,40 @@ from .ssh import (
30
38
  )
31
39
 
32
40
 
41
+ def get_common_variables(target_profile: HostProfile, controller: bool = False) -> dict[str, t.Any]:
42
+ """Get variables common to all scenarios, but dependent on the target profile."""
43
+ target_config = target_profile.config
44
+
45
+ if controller or isinstance(target_config, ControllerConfig):
46
+ # The current process is running on the controller, so consult the controller directly when it is the target.
47
+ macos = sys.platform == 'darwin'
48
+ elif isinstance(target_config, PosixRemoteConfig):
49
+ # The target is not the controller, so consult the remote config for that target.
50
+ macos = target_config.name.startswith('macos/')
51
+ else:
52
+ # The target is a type which either cannot be macOS or for which the OS is unknown.
53
+ # There is currently no means for the user to override this for user provided hosts.
54
+ macos = False
55
+
56
+ common_variables: dict[str, t.Any] = {}
57
+
58
+ if macos:
59
+ # When using sudo on macOS we may encounter permission denied errors when dropping privileges due to inability to access the current working directory.
60
+ # To compensate for this we'll perform a `cd /` before running any commands after `sudo` succeeds.
61
+ common_variables.update(ansible_sudo_chdir='/')
62
+
63
+ if isinstance(target_profile, DebuggableProfile):
64
+ common_variables.update(target_profile.get_ansiballz_inventory_variables())
65
+
66
+ return common_variables
67
+
68
+
33
69
  def create_controller_inventory(args: EnvironmentConfig, path: str, controller_host: ControllerHostProfile) -> None:
34
70
  """Create and return inventory for use in controller-only integration tests."""
35
71
  inventory = Inventory(
36
72
  host_groups=dict(
37
73
  testgroup=dict(
38
- testhost=dict(
74
+ testhost=get_common_variables(controller_host, controller=True) | dict(
39
75
  ansible_connection='local',
40
76
  ansible_pipelining='yes',
41
77
  ansible_python_interpreter=controller_host.python.path,
@@ -129,7 +165,7 @@ def create_posix_inventory(args: EnvironmentConfig, path: str, target_hosts: lis
129
165
  inventory = Inventory(
130
166
  host_groups=dict(
131
167
  testgroup=dict(
132
- testhost=dict(
168
+ testhost=get_common_variables(target_host) | dict(
133
169
  ansible_connection='local',
134
170
  ansible_pipelining='yes',
135
171
  ansible_python_interpreter=target_host.python.path,
@@ -145,7 +181,7 @@ def create_posix_inventory(args: EnvironmentConfig, path: str, target_hosts: lis
145
181
 
146
182
  ssh = connections[0]
147
183
 
148
- testhost: dict[str, t.Optional[t.Union[str, int]]] = dict(
184
+ testhost: dict[str, t.Optional[t.Union[str, int]]] = get_common_variables(target_host) | dict(
149
185
  ansible_connection='ssh',
150
186
  ansible_pipelining='yes',
151
187
  ansible_python_interpreter=ssh.settings.python_interpreter,
@@ -1,4 +1,5 @@
1
1
  """Functions for disk IO."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  import io