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

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

Potentially problematic release.


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

Files changed (757) hide show
  1. ansible/_internal/__init__.py +53 -0
  2. ansible/_internal/_ansiballz/__init__.py +0 -0
  3. ansible/_internal/_ansiballz/_builder.py +101 -0
  4. ansible/_internal/_ansiballz/_wrapper.py +262 -0
  5. ansible/_internal/_collection_proxy.py +47 -0
  6. ansible/_internal/_datatag/__init__.py +0 -0
  7. ansible/_internal/_datatag/_tags.py +130 -0
  8. ansible/_internal/_datatag/_utils.py +19 -0
  9. ansible/_internal/_datatag/_wrappers.py +33 -0
  10. ansible/_internal/_errors/__init__.py +0 -0
  11. ansible/_internal/_errors/_alarm_timeout.py +66 -0
  12. ansible/_internal/_errors/_captured.py +123 -0
  13. ansible/_internal/_errors/_error_factory.py +89 -0
  14. ansible/_internal/_errors/_error_utils.py +240 -0
  15. ansible/_internal/_errors/_handler.py +91 -0
  16. ansible/_internal/_errors/_task_timeout.py +28 -0
  17. ansible/_internal/_event_formatting.py +127 -0
  18. ansible/_internal/_json/__init__.py +214 -0
  19. ansible/_internal/_json/_legacy_encoder.py +34 -0
  20. ansible/_internal/_json/_profiles/__init__.py +0 -0
  21. ansible/_internal/_json/_profiles/_cache_persistence.py +57 -0
  22. ansible/_internal/_json/_profiles/_inventory_legacy.py +40 -0
  23. ansible/_internal/_json/_profiles/_legacy.py +189 -0
  24. ansible/_internal/_locking.py +21 -0
  25. ansible/_internal/_plugins/__init__.py +0 -0
  26. ansible/_internal/_plugins/_cache.py +57 -0
  27. ansible/_internal/_ssh/__init__.py +0 -0
  28. ansible/_internal/_ssh/_agent_launch.py +91 -0
  29. ansible/_internal/_ssh/_ssh_agent.py +619 -0
  30. ansible/_internal/_task.py +78 -0
  31. ansible/_internal/_templating/__init__.py +12 -0
  32. ansible/_internal/_templating/_access.py +86 -0
  33. ansible/_internal/_templating/_chain_templar.py +63 -0
  34. ansible/_internal/_templating/_datatag.py +95 -0
  35. ansible/_internal/_templating/_engine.py +592 -0
  36. ansible/_internal/_templating/_errors.py +28 -0
  37. ansible/_internal/_templating/_jinja_bits.py +1106 -0
  38. ansible/_internal/_templating/_jinja_common.py +323 -0
  39. ansible/_internal/_templating/_jinja_patches.py +44 -0
  40. ansible/_internal/_templating/_jinja_plugins.py +375 -0
  41. ansible/_internal/_templating/_lazy_containers.py +633 -0
  42. ansible/_internal/_templating/_marker_behaviors.py +103 -0
  43. ansible/_internal/_templating/_template_vars.py +72 -0
  44. ansible/_internal/_templating/_transform.py +70 -0
  45. ansible/_internal/_templating/_utils.py +108 -0
  46. ansible/_internal/_testing.py +26 -0
  47. ansible/_internal/_wrapt.py +1052 -0
  48. ansible/_internal/_yaml/__init__.py +0 -0
  49. ansible/_internal/_yaml/_constructor.py +240 -0
  50. ansible/_internal/_yaml/_dumper.py +70 -0
  51. ansible/_internal/_yaml/_errors.py +166 -0
  52. ansible/_internal/_yaml/_loader.py +66 -0
  53. ansible/_internal/ansible_collections/ansible/_protomatter/README.md +11 -0
  54. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/action/debug.py +36 -0
  55. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/apply_trust.py +19 -0
  56. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/dump_object.py +27 -0
  57. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/finalize.py +16 -0
  58. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/origin.py +18 -0
  59. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/python_literal_eval.py +24 -0
  60. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/python_literal_eval.yml +33 -0
  61. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/tag_names.py +16 -0
  62. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/true_type.py +17 -0
  63. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/unmask.py +49 -0
  64. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/lookup/config.py +21 -0
  65. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/lookup/config.yml +2 -0
  66. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged.py +15 -0
  67. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged.yml +19 -0
  68. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged_with.py +18 -0
  69. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged_with.yml +19 -0
  70. ansible/cli/__init__.py +93 -104
  71. ansible/cli/_ssh_askpass.py +54 -0
  72. ansible/cli/adhoc.py +20 -10
  73. ansible/cli/arguments/option_helpers.py +163 -10
  74. ansible/cli/config.py +43 -68
  75. ansible/cli/console.py +13 -11
  76. ansible/cli/doc.py +134 -77
  77. ansible/cli/galaxy.py +27 -20
  78. ansible/cli/inventory.py +28 -28
  79. ansible/cli/playbook.py +4 -12
  80. ansible/cli/pull.py +6 -3
  81. ansible/cli/scripts/ansible_connection_cli_stub.py +7 -7
  82. ansible/cli/vault.py +12 -11
  83. ansible/compat/__init__.py +2 -2
  84. ansible/compat/importlib_resources.py +9 -12
  85. ansible/config/base.yml +218 -133
  86. ansible/config/manager.py +220 -159
  87. ansible/constants.py +2 -65
  88. ansible/errors/__init__.py +350 -256
  89. ansible/executor/interpreter_discovery.py +28 -149
  90. ansible/executor/module_common.py +480 -514
  91. ansible/executor/play_iterator.py +22 -27
  92. ansible/executor/playbook_executor.py +11 -11
  93. ansible/executor/powershell/async_watchdog.ps1 +97 -102
  94. ansible/executor/powershell/async_wrapper.ps1 +204 -153
  95. ansible/executor/powershell/become_wrapper.ps1 +107 -144
  96. ansible/executor/powershell/bootstrap_wrapper.ps1 +46 -9
  97. ansible/executor/powershell/coverage_wrapper.ps1 +91 -135
  98. ansible/executor/powershell/exec_wrapper.ps1 +675 -196
  99. ansible/executor/powershell/module_manifest.py +469 -265
  100. ansible/executor/powershell/module_wrapper.ps1 +195 -186
  101. ansible/executor/powershell/powershell_expand_user.ps1 +20 -0
  102. ansible/executor/powershell/powershell_mkdtemp.ps1 +17 -0
  103. ansible/executor/powershell/psrp_fetch_file.ps1 +41 -0
  104. ansible/executor/powershell/psrp_put_file.ps1 +122 -0
  105. ansible/executor/powershell/winrm_fetch_file.ps1 +46 -0
  106. ansible/executor/powershell/winrm_put_file.ps1 +36 -0
  107. ansible/executor/process/worker.py +139 -149
  108. ansible/executor/stats.py +5 -5
  109. ansible/executor/task_executor.py +270 -297
  110. ansible/executor/task_queue_manager.py +135 -137
  111. ansible/executor/task_result.py +182 -79
  112. ansible/galaxy/__init__.py +2 -2
  113. ansible/galaxy/api.py +26 -25
  114. ansible/galaxy/collection/__init__.py +6 -14
  115. ansible/galaxy/collection/concrete_artifact_manager.py +12 -21
  116. ansible/galaxy/dependency_resolution/dataclasses.py +14 -4
  117. ansible/galaxy/dependency_resolution/providers.py +4 -4
  118. ansible/galaxy/dependency_resolution/reporters.py +81 -0
  119. ansible/galaxy/role.py +6 -10
  120. ansible/galaxy/token.py +28 -21
  121. ansible/inventory/data.py +47 -57
  122. ansible/inventory/group.py +50 -73
  123. ansible/inventory/helpers.py +9 -0
  124. ansible/inventory/host.py +37 -54
  125. ansible/inventory/manager.py +79 -34
  126. ansible/keyword_desc.yml +1 -1
  127. ansible/module_utils/_internal/__init__.py +55 -0
  128. ansible/module_utils/_internal/_ambient_context.py +58 -0
  129. ansible/module_utils/_internal/_ansiballz/__init__.py +0 -0
  130. ansible/module_utils/_internal/_ansiballz/_extensions/__init__.py +0 -0
  131. ansible/module_utils/_internal/_ansiballz/_extensions/_coverage.py +45 -0
  132. ansible/module_utils/_internal/_ansiballz/_extensions/_pydevd.py +62 -0
  133. ansible/module_utils/_internal/_ansiballz/_loader.py +81 -0
  134. ansible/module_utils/_internal/_ansiballz/_respawn.py +32 -0
  135. ansible/module_utils/_internal/_ansiballz/_respawn_wrapper.py +23 -0
  136. ansible/module_utils/_internal/_concurrent/_daemon_threading.py +1 -0
  137. ansible/module_utils/_internal/_dataclass_validation.py +217 -0
  138. ansible/module_utils/_internal/_datatag/__init__.py +961 -0
  139. ansible/module_utils/_internal/_datatag/_tags.py +16 -0
  140. ansible/module_utils/_internal/_debugging.py +31 -0
  141. ansible/module_utils/_internal/_deprecator.py +157 -0
  142. ansible/module_utils/_internal/_errors.py +101 -0
  143. ansible/module_utils/_internal/_event_utils.py +61 -0
  144. ansible/module_utils/_internal/_json/__init__.py +63 -0
  145. ansible/module_utils/_internal/_json/_legacy_encoder.py +26 -0
  146. ansible/module_utils/_internal/_json/_profiles/__init__.py +428 -0
  147. ansible/module_utils/_internal/_json/_profiles/_fallback_to_str.py +73 -0
  148. ansible/module_utils/_internal/_json/_profiles/_module_legacy_c2m.py +33 -0
  149. ansible/module_utils/_internal/_json/_profiles/_module_legacy_m2c.py +37 -0
  150. ansible/module_utils/_internal/_json/_profiles/_module_modern_c2m.py +35 -0
  151. ansible/module_utils/_internal/_json/_profiles/_module_modern_m2c.py +33 -0
  152. ansible/module_utils/_internal/_json/_profiles/_tagless.py +52 -0
  153. ansible/module_utils/_internal/_messages.py +130 -0
  154. ansible/module_utils/_internal/_patches/__init__.py +66 -0
  155. ansible/module_utils/_internal/_patches/_dataclass_annotation_patch.py +53 -0
  156. ansible/module_utils/_internal/_patches/_socket_patch.py +34 -0
  157. ansible/module_utils/_internal/_patches/_sys_intern_patch.py +34 -0
  158. ansible/module_utils/_internal/_plugin_info.py +38 -0
  159. ansible/module_utils/_internal/_stack.py +22 -0
  160. ansible/module_utils/_internal/_testing.py +0 -0
  161. ansible/module_utils/_internal/_text_utils.py +6 -0
  162. ansible/module_utils/_internal/_traceback.py +92 -0
  163. ansible/module_utils/_internal/_validation.py +14 -0
  164. ansible/module_utils/ansible_release.py +2 -2
  165. ansible/module_utils/api.py +1 -2
  166. ansible/module_utils/basic.py +303 -202
  167. ansible/module_utils/common/_utils.py +24 -28
  168. ansible/module_utils/common/arg_spec.py +8 -3
  169. ansible/module_utils/common/collections.py +7 -2
  170. ansible/module_utils/common/dict_transformations.py +2 -2
  171. ansible/module_utils/common/file.py +2 -2
  172. ansible/module_utils/common/json.py +90 -84
  173. ansible/module_utils/common/locale.py +2 -2
  174. ansible/module_utils/common/parameters.py +27 -24
  175. ansible/module_utils/common/process.py +2 -3
  176. ansible/module_utils/common/respawn.py +11 -33
  177. ansible/module_utils/common/sentinel.py +66 -0
  178. ansible/module_utils/common/sys_info.py +8 -8
  179. ansible/module_utils/common/text/converters.py +16 -37
  180. ansible/module_utils/common/validation.py +35 -24
  181. ansible/module_utils/common/warnings.py +143 -25
  182. ansible/module_utils/common/yaml.py +29 -3
  183. ansible/module_utils/compat/datetime.py +33 -21
  184. ansible/module_utils/compat/paramiko.py +21 -10
  185. ansible/module_utils/compat/typing.py +6 -5
  186. ansible/module_utils/connection.py +10 -13
  187. ansible/module_utils/csharp/Ansible.Basic.cs +15 -12
  188. ansible/module_utils/csharp/Ansible.Become.cs +1 -0
  189. ansible/module_utils/csharp/Ansible.Privilege.cs +2 -2
  190. ansible/module_utils/csharp/Ansible._Async.cs +517 -0
  191. ansible/module_utils/datatag.py +49 -0
  192. ansible/module_utils/distro/__init__.py +2 -2
  193. ansible/module_utils/facts/ansible_collector.py +4 -5
  194. ansible/module_utils/facts/collector.py +13 -14
  195. ansible/module_utils/facts/compat.py +4 -4
  196. ansible/module_utils/facts/default_collectors.py +1 -1
  197. ansible/module_utils/facts/hardware/aix.py +34 -0
  198. ansible/module_utils/facts/hardware/base.py +2 -2
  199. ansible/module_utils/facts/hardware/darwin.py +1 -3
  200. ansible/module_utils/facts/hardware/freebsd.py +2 -2
  201. ansible/module_utils/facts/hardware/linux.py +5 -5
  202. ansible/module_utils/facts/namespace.py +1 -1
  203. ansible/module_utils/facts/network/base.py +1 -1
  204. ansible/module_utils/facts/network/fc_wwn.py +1 -2
  205. ansible/module_utils/facts/network/iscsi.py +1 -2
  206. ansible/module_utils/facts/network/nvme.py +1 -2
  207. ansible/module_utils/facts/other/facter.py +2 -3
  208. ansible/module_utils/facts/other/ohai.py +2 -3
  209. ansible/module_utils/facts/sysctl.py +4 -6
  210. ansible/module_utils/facts/system/apparmor.py +1 -2
  211. ansible/module_utils/facts/system/caps.py +3 -3
  212. ansible/module_utils/facts/system/chroot.py +1 -2
  213. ansible/module_utils/facts/system/cmdline.py +1 -2
  214. ansible/module_utils/facts/system/date_time.py +5 -3
  215. ansible/module_utils/facts/system/distribution.py +27 -13
  216. ansible/module_utils/facts/system/dns.py +1 -1
  217. ansible/module_utils/facts/system/env.py +1 -2
  218. ansible/module_utils/facts/system/fips.py +7 -20
  219. ansible/module_utils/facts/system/loadavg.py +1 -2
  220. ansible/module_utils/facts/system/local.py +2 -3
  221. ansible/module_utils/facts/system/lsb.py +1 -2
  222. ansible/module_utils/facts/system/pkg_mgr.py +1 -2
  223. ansible/module_utils/facts/system/platform.py +1 -2
  224. ansible/module_utils/facts/system/python.py +1 -2
  225. ansible/module_utils/facts/system/selinux.py +1 -1
  226. ansible/module_utils/facts/system/service_mgr.py +1 -2
  227. ansible/module_utils/facts/system/ssh_pub_keys.py +1 -1
  228. ansible/module_utils/facts/system/systemd.py +1 -1
  229. ansible/module_utils/facts/system/user.py +1 -2
  230. ansible/module_utils/facts/utils.py +3 -3
  231. ansible/module_utils/facts/virtual/base.py +1 -1
  232. ansible/module_utils/facts/virtual/linux.py +3 -3
  233. ansible/module_utils/facts/virtual/sunos.py +3 -15
  234. ansible/module_utils/facts/virtual/sysctl.py +3 -16
  235. ansible/module_utils/json_utils.py +2 -2
  236. ansible/module_utils/parsing/convert_bool.py +7 -1
  237. ansible/module_utils/powershell/Ansible.ModuleUtils.AddType.psm1 +1 -1
  238. ansible/module_utils/powershell/Ansible.ModuleUtils.CamelConversion.psm1 +1 -1
  239. ansible/module_utils/powershell/Ansible.ModuleUtils.CommandUtil.psm1 +1 -1
  240. ansible/module_utils/powershell/Ansible.ModuleUtils.WebRequest.psm1 +1 -1
  241. ansible/module_utils/service.py +21 -31
  242. ansible/module_utils/splitter.py +7 -7
  243. ansible/module_utils/testing.py +31 -0
  244. ansible/module_utils/urls.py +64 -35
  245. ansible/modules/add_host.py +4 -4
  246. ansible/modules/apt.py +69 -49
  247. ansible/modules/apt_key.py +19 -12
  248. ansible/modules/apt_repository.py +32 -51
  249. ansible/modules/assemble.py +16 -14
  250. ansible/modules/assert.py +4 -4
  251. ansible/modules/async_status.py +24 -24
  252. ansible/modules/async_wrapper.py +20 -25
  253. ansible/modules/blockinfile.py +6 -7
  254. ansible/modules/command.py +13 -20
  255. ansible/modules/copy.py +60 -147
  256. ansible/modules/cron.py +24 -21
  257. ansible/modules/deb822_repository.py +8 -9
  258. ansible/modules/debconf.py +5 -5
  259. ansible/modules/debug.py +4 -4
  260. ansible/modules/dnf.py +8 -8
  261. ansible/modules/dnf5.py +39 -13
  262. ansible/modules/dpkg_selections.py +4 -4
  263. ansible/modules/expect.py +13 -15
  264. ansible/modules/fail.py +4 -4
  265. ansible/modules/fetch.py +4 -4
  266. ansible/modules/file.py +184 -144
  267. ansible/modules/find.py +22 -20
  268. ansible/modules/gather_facts.py +3 -3
  269. ansible/modules/get_url.py +77 -54
  270. ansible/modules/getent.py +7 -9
  271. ansible/modules/git.py +38 -38
  272. ansible/modules/group.py +6 -6
  273. ansible/modules/group_by.py +4 -4
  274. ansible/modules/hostname.py +15 -32
  275. ansible/modules/import_playbook.py +6 -6
  276. ansible/modules/import_role.py +6 -6
  277. ansible/modules/import_tasks.py +6 -6
  278. ansible/modules/include_role.py +6 -6
  279. ansible/modules/include_tasks.py +6 -6
  280. ansible/modules/include_vars.py +6 -6
  281. ansible/modules/iptables.py +86 -73
  282. ansible/modules/known_hosts.py +22 -24
  283. ansible/modules/lineinfile.py +5 -5
  284. ansible/modules/meta.py +4 -4
  285. ansible/modules/mount_facts.py +2 -2
  286. ansible/modules/package.py +10 -4
  287. ansible/modules/package_facts.py +22 -10
  288. ansible/modules/pause.py +6 -6
  289. ansible/modules/ping.py +6 -6
  290. ansible/modules/pip.py +21 -26
  291. ansible/modules/raw.py +6 -6
  292. ansible/modules/reboot.py +6 -6
  293. ansible/modules/replace.py +10 -14
  294. ansible/modules/rpm_key.py +7 -8
  295. ansible/modules/script.py +4 -4
  296. ansible/modules/service.py +10 -17
  297. ansible/modules/service_facts.py +87 -10
  298. ansible/modules/set_fact.py +5 -5
  299. ansible/modules/set_stats.py +4 -4
  300. ansible/modules/setup.py +2 -2
  301. ansible/modules/shell.py +6 -6
  302. ansible/modules/slurp.py +16 -19
  303. ansible/modules/stat.py +15 -31
  304. ansible/modules/subversion.py +15 -15
  305. ansible/modules/systemd.py +7 -7
  306. ansible/modules/systemd_service.py +7 -7
  307. ansible/modules/sysvinit.py +9 -9
  308. ansible/modules/tempfile.py +5 -6
  309. ansible/modules/template.py +6 -6
  310. ansible/modules/unarchive.py +38 -17
  311. ansible/modules/uri.py +33 -26
  312. ansible/modules/user.py +45 -32
  313. ansible/modules/validate_argument_spec.py +10 -7
  314. ansible/modules/wait_for.py +70 -60
  315. ansible/modules/wait_for_connection.py +6 -6
  316. ansible/modules/yum_repository.py +10 -9
  317. ansible/parsing/ajson.py +17 -37
  318. ansible/parsing/dataloader.py +99 -54
  319. ansible/parsing/mod_args.py +62 -60
  320. ansible/parsing/plugin_docs.py +21 -86
  321. ansible/parsing/quoting.py +1 -1
  322. ansible/parsing/splitter.py +27 -12
  323. ansible/parsing/utils/addresses.py +24 -24
  324. ansible/parsing/utils/jsonify.py +5 -1
  325. ansible/parsing/utils/yaml.py +32 -61
  326. ansible/parsing/vault/__init__.py +327 -99
  327. ansible/parsing/yaml/__init__.py +0 -18
  328. ansible/parsing/yaml/dumper.py +6 -120
  329. ansible/parsing/yaml/loader.py +6 -39
  330. ansible/parsing/yaml/objects.py +43 -335
  331. ansible/playbook/__init__.py +1 -1
  332. ansible/playbook/attribute.py +8 -3
  333. ansible/playbook/base.py +187 -134
  334. ansible/playbook/block.py +26 -24
  335. ansible/playbook/collectionsearch.py +1 -15
  336. ansible/playbook/conditional.py +3 -77
  337. ansible/playbook/handler.py +8 -2
  338. ansible/playbook/helpers.py +41 -53
  339. ansible/playbook/included_file.py +32 -26
  340. ansible/playbook/loop_control.py +2 -2
  341. ansible/playbook/play.py +85 -44
  342. ansible/playbook/play_context.py +14 -17
  343. ansible/playbook/playbook_include.py +27 -62
  344. ansible/playbook/role/__init__.py +64 -49
  345. ansible/playbook/role/definition.py +15 -17
  346. ansible/playbook/role/include.py +2 -4
  347. ansible/playbook/role/metadata.py +10 -11
  348. ansible/playbook/role_include.py +3 -3
  349. ansible/playbook/taggable.py +28 -12
  350. ansible/playbook/task.py +192 -121
  351. ansible/playbook/task_include.py +5 -5
  352. ansible/plugins/__init__.py +58 -26
  353. ansible/plugins/action/__init__.py +188 -186
  354. ansible/plugins/action/add_host.py +2 -2
  355. ansible/plugins/action/assemble.py +11 -18
  356. ansible/plugins/action/assert.py +55 -67
  357. ansible/plugins/action/async_status.py +7 -2
  358. ansible/plugins/action/copy.py +14 -17
  359. ansible/plugins/action/debug.py +37 -31
  360. ansible/plugins/action/dnf.py +3 -4
  361. ansible/plugins/action/fail.py +1 -1
  362. ansible/plugins/action/fetch.py +7 -8
  363. ansible/plugins/action/gather_facts.py +13 -14
  364. ansible/plugins/action/group_by.py +1 -1
  365. ansible/plugins/action/include_vars.py +10 -11
  366. ansible/plugins/action/package.py +8 -14
  367. ansible/plugins/action/pause.py +2 -2
  368. ansible/plugins/action/script.py +27 -38
  369. ansible/plugins/action/service.py +9 -18
  370. ansible/plugins/action/set_fact.py +3 -12
  371. ansible/plugins/action/set_stats.py +3 -8
  372. ansible/plugins/action/template.py +47 -67
  373. ansible/plugins/action/unarchive.py +6 -16
  374. ansible/plugins/action/uri.py +9 -20
  375. ansible/plugins/action/validate_argument_spec.py +5 -5
  376. ansible/plugins/action/wait_for_connection.py +1 -1
  377. ansible/plugins/become/__init__.py +31 -8
  378. ansible/plugins/become/runas.py +71 -0
  379. ansible/plugins/become/su.py +13 -8
  380. ansible/plugins/become/sudo.py +19 -0
  381. ansible/plugins/cache/__init__.py +52 -63
  382. ansible/plugins/cache/base.py +8 -0
  383. ansible/plugins/cache/jsonfile.py +10 -16
  384. ansible/plugins/cache/memory.py +6 -12
  385. ansible/plugins/callback/__init__.py +294 -201
  386. ansible/plugins/callback/default.py +99 -95
  387. ansible/plugins/callback/junit.py +44 -43
  388. ansible/plugins/callback/minimal.py +28 -25
  389. ansible/plugins/callback/oneline.py +34 -21
  390. ansible/plugins/callback/tree.py +27 -16
  391. ansible/plugins/connection/__init__.py +47 -34
  392. ansible/plugins/connection/local.py +156 -60
  393. ansible/plugins/connection/paramiko_ssh.py +34 -24
  394. ansible/plugins/connection/psrp.py +76 -165
  395. ansible/plugins/connection/ssh.py +326 -86
  396. ansible/plugins/connection/winrm.py +62 -141
  397. ansible/plugins/doc_fragments/action_common_attributes.py +14 -14
  398. ansible/plugins/doc_fragments/action_core.py +6 -6
  399. ansible/plugins/doc_fragments/backup.py +2 -2
  400. ansible/plugins/doc_fragments/checksum_common.py +27 -0
  401. ansible/plugins/doc_fragments/constructed.py +8 -4
  402. ansible/plugins/doc_fragments/decrypt.py +2 -2
  403. ansible/plugins/doc_fragments/default_callback.py +2 -2
  404. ansible/plugins/doc_fragments/files.py +2 -2
  405. ansible/plugins/doc_fragments/inventory_cache.py +2 -2
  406. ansible/plugins/doc_fragments/result_format_callback.py +2 -2
  407. ansible/plugins/doc_fragments/return_common.py +2 -2
  408. ansible/plugins/doc_fragments/template_common.py +4 -4
  409. ansible/plugins/doc_fragments/url.py +17 -1
  410. ansible/plugins/doc_fragments/url_windows.py +2 -2
  411. ansible/plugins/doc_fragments/validate.py +2 -2
  412. ansible/plugins/doc_fragments/vars_plugin_staging.py +2 -2
  413. ansible/plugins/filter/__init__.py +6 -2
  414. ansible/plugins/filter/b64decode.yml +22 -0
  415. ansible/plugins/filter/b64encode.yml +22 -0
  416. ansible/plugins/filter/bool.yml +11 -4
  417. ansible/plugins/filter/core.py +245 -120
  418. ansible/plugins/filter/encryption.py +42 -34
  419. ansible/plugins/filter/flatten.yml +3 -2
  420. ansible/plugins/filter/human_to_bytes.yml +1 -1
  421. ansible/plugins/filter/mathstuff.py +30 -37
  422. ansible/plugins/filter/password_hash.yml +8 -0
  423. ansible/plugins/filter/pow.yml +1 -1
  424. ansible/plugins/filter/regex_search.yml +1 -4
  425. ansible/plugins/filter/root.yml +1 -1
  426. ansible/plugins/filter/split.yml +1 -1
  427. ansible/plugins/filter/strftime.yml +3 -3
  428. ansible/plugins/filter/to_nice_yaml.yml +0 -4
  429. ansible/plugins/filter/to_uuid.yml +1 -1
  430. ansible/plugins/filter/to_yaml.yml +0 -4
  431. ansible/plugins/filter/unvault.yml +1 -1
  432. ansible/plugins/filter/urls.py +1 -1
  433. ansible/plugins/filter/urlsplit.py +8 -9
  434. ansible/plugins/filter/vault.yml +14 -9
  435. ansible/plugins/filter/win_basename.yml +6 -1
  436. ansible/plugins/filter/win_dirname.yml +5 -0
  437. ansible/plugins/inventory/__init__.py +107 -86
  438. ansible/plugins/inventory/advanced_host_list.py +7 -5
  439. ansible/plugins/inventory/auto.py +11 -4
  440. ansible/plugins/inventory/constructed.py +21 -24
  441. ansible/plugins/inventory/generator.py +16 -11
  442. ansible/plugins/inventory/host_list.py +7 -5
  443. ansible/plugins/inventory/ini.py +78 -44
  444. ansible/plugins/inventory/script.py +190 -120
  445. ansible/plugins/inventory/toml.py +16 -126
  446. ansible/plugins/inventory/yaml.py +10 -8
  447. ansible/plugins/list.py +72 -19
  448. ansible/plugins/loader.py +383 -198
  449. ansible/plugins/lookup/__init__.py +21 -4
  450. ansible/plugins/lookup/config.py +21 -35
  451. ansible/plugins/lookup/csvfile.py +19 -73
  452. ansible/plugins/lookup/dict.py +1 -6
  453. ansible/plugins/lookup/env.py +12 -9
  454. ansible/plugins/lookup/file.py +5 -8
  455. ansible/plugins/lookup/first_found.py +87 -55
  456. ansible/plugins/lookup/indexed_items.py +1 -10
  457. ansible/plugins/lookup/ini.py +14 -13
  458. ansible/plugins/lookup/items.py +1 -1
  459. ansible/plugins/lookup/lines.py +8 -1
  460. ansible/plugins/lookup/list.py +1 -1
  461. ansible/plugins/lookup/nested.py +2 -18
  462. ansible/plugins/lookup/password.py +5 -5
  463. ansible/plugins/lookup/pipe.py +5 -7
  464. ansible/plugins/lookup/sequence.py +18 -8
  465. ansible/plugins/lookup/subelements.py +1 -4
  466. ansible/plugins/lookup/template.py +47 -36
  467. ansible/plugins/lookup/together.py +0 -12
  468. ansible/plugins/lookup/unvault.py +1 -5
  469. ansible/plugins/lookup/url.py +4 -10
  470. ansible/plugins/lookup/vars.py +16 -24
  471. ansible/plugins/shell/__init__.py +58 -4
  472. ansible/plugins/shell/cmd.py +2 -2
  473. ansible/plugins/shell/powershell.py +106 -31
  474. ansible/plugins/shell/sh.py +13 -7
  475. ansible/plugins/strategy/__init__.py +168 -193
  476. ansible/plugins/strategy/debug.py +2 -2
  477. ansible/plugins/strategy/free.py +16 -31
  478. ansible/plugins/strategy/host_pinned.py +2 -2
  479. ansible/plugins/strategy/linear.py +41 -41
  480. ansible/plugins/terminal/__init__.py +4 -4
  481. ansible/plugins/test/__init__.py +7 -2
  482. ansible/plugins/test/core.py +75 -35
  483. ansible/plugins/test/files.py +1 -1
  484. ansible/plugins/test/finished.yml +1 -1
  485. ansible/plugins/test/mathstuff.py +3 -3
  486. ansible/plugins/test/uri.py +5 -8
  487. ansible/plugins/vars/host_group_vars.py +7 -14
  488. ansible/release.py +2 -2
  489. ansible/template/__init__.py +353 -943
  490. ansible/utils/__init__.py +0 -18
  491. ansible/utils/collection_loader/__init__.py +54 -5
  492. ansible/utils/collection_loader/_collection_config.py +5 -6
  493. ansible/utils/collection_loader/_collection_finder.py +82 -96
  494. ansible/utils/collection_loader/_collection_meta.py +15 -8
  495. ansible/utils/display.py +485 -73
  496. ansible/utils/encrypt.py +27 -19
  497. ansible/utils/fqcn.py +2 -2
  498. ansible/utils/galaxy.py +2 -2
  499. ansible/utils/hashing.py +8 -10
  500. ansible/utils/helpers.py +2 -2
  501. ansible/utils/listify.py +10 -8
  502. ansible/utils/lock.py +2 -2
  503. ansible/utils/path.py +10 -12
  504. ansible/utils/plugin_docs.py +16 -14
  505. ansible/utils/py3compat.py +2 -7
  506. ansible/utils/sentinel.py +4 -62
  507. ansible/utils/singleton.py +2 -0
  508. ansible/utils/ssh_functions.py +6 -2
  509. ansible/utils/unsafe_proxy.py +23 -332
  510. ansible/utils/vars.py +55 -8
  511. ansible/utils/version.py +2 -2
  512. ansible/vars/clean.py +5 -5
  513. ansible/vars/hostvars.py +60 -90
  514. ansible/vars/manager.py +220 -285
  515. ansible/vars/plugins.py +4 -4
  516. ansible/vars/reserved.py +13 -12
  517. {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/METADATA +4 -3
  518. ansible_core-2.19.0.dist-info/RECORD +1097 -0
  519. ansible_core-2.19.0.dist-info/licenses/licenses/BSD-3-Clause.txt +28 -0
  520. ansible_test/_data/completion/docker.txt +7 -7
  521. ansible_test/_data/completion/remote.txt +6 -6
  522. ansible_test/_data/completion/windows.txt +1 -0
  523. ansible_test/_data/requirements/ansible.txt +2 -2
  524. ansible_test/_data/requirements/sanity.ansible-doc.txt +3 -3
  525. ansible_test/_data/requirements/sanity.changelog.txt +2 -2
  526. ansible_test/_data/requirements/sanity.import.plugin.txt +2 -2
  527. ansible_test/_data/requirements/sanity.pep8.txt +1 -1
  528. ansible_test/_data/requirements/sanity.pylint.txt +5 -5
  529. ansible_test/_data/requirements/sanity.validate-modules.txt +2 -2
  530. ansible_test/_data/requirements/sanity.yamllint.txt +1 -1
  531. ansible_test/_data/requirements/units.txt +1 -0
  532. ansible_test/_internal/__init__.py +6 -0
  533. ansible_test/_internal/ansible_util.py +3 -1
  534. ansible_test/_internal/become.py +1 -0
  535. ansible_test/_internal/bootstrap.py +1 -0
  536. ansible_test/_internal/cache.py +1 -0
  537. ansible_test/_internal/cgroup.py +1 -0
  538. ansible_test/_internal/ci/__init__.py +1 -0
  539. ansible_test/_internal/ci/azp.py +1 -0
  540. ansible_test/_internal/ci/local.py +1 -0
  541. ansible_test/_internal/classification/__init__.py +1 -0
  542. ansible_test/_internal/classification/common.py +1 -0
  543. ansible_test/_internal/classification/csharp.py +1 -0
  544. ansible_test/_internal/classification/powershell.py +1 -0
  545. ansible_test/_internal/classification/python.py +1 -0
  546. ansible_test/_internal/cli/__init__.py +1 -0
  547. ansible_test/_internal/cli/actions.py +1 -0
  548. ansible_test/_internal/cli/argparsing/__init__.py +1 -0
  549. ansible_test/_internal/cli/argparsing/actions.py +1 -0
  550. ansible_test/_internal/cli/argparsing/argcompletion.py +1 -0
  551. ansible_test/_internal/cli/argparsing/parsers.py +1 -0
  552. ansible_test/_internal/cli/commands/__init__.py +11 -5
  553. ansible_test/_internal/cli/commands/coverage/__init__.py +1 -0
  554. ansible_test/_internal/cli/commands/coverage/analyze/__init__.py +1 -0
  555. ansible_test/_internal/cli/commands/coverage/analyze/targets/__init__.py +1 -0
  556. ansible_test/_internal/cli/commands/coverage/analyze/targets/combine.py +1 -0
  557. ansible_test/_internal/cli/commands/coverage/analyze/targets/expand.py +1 -0
  558. ansible_test/_internal/cli/commands/coverage/analyze/targets/filter.py +1 -0
  559. ansible_test/_internal/cli/commands/coverage/analyze/targets/generate.py +1 -0
  560. ansible_test/_internal/cli/commands/coverage/analyze/targets/missing.py +1 -0
  561. ansible_test/_internal/cli/commands/coverage/combine.py +1 -0
  562. ansible_test/_internal/cli/commands/coverage/erase.py +1 -0
  563. ansible_test/_internal/cli/commands/coverage/html.py +1 -0
  564. ansible_test/_internal/cli/commands/coverage/report.py +1 -0
  565. ansible_test/_internal/cli/commands/coverage/xml.py +1 -0
  566. ansible_test/_internal/cli/commands/env.py +1 -0
  567. ansible_test/_internal/cli/commands/integration/__init__.py +1 -0
  568. ansible_test/_internal/cli/commands/integration/network.py +1 -0
  569. ansible_test/_internal/cli/commands/integration/posix.py +1 -0
  570. ansible_test/_internal/cli/commands/integration/windows.py +1 -0
  571. ansible_test/_internal/cli/commands/sanity.py +9 -0
  572. ansible_test/_internal/cli/commands/shell.py +1 -0
  573. ansible_test/_internal/cli/commands/units.py +1 -0
  574. ansible_test/_internal/cli/compat.py +1 -0
  575. ansible_test/_internal/cli/completers.py +1 -0
  576. ansible_test/_internal/cli/converters.py +1 -0
  577. ansible_test/_internal/cli/environments.py +52 -5
  578. ansible_test/_internal/cli/epilog.py +1 -0
  579. ansible_test/_internal/cli/parsers/__init__.py +1 -0
  580. ansible_test/_internal/cli/parsers/base_argument_parsers.py +1 -0
  581. ansible_test/_internal/cli/parsers/helpers.py +1 -0
  582. ansible_test/_internal/cli/parsers/host_config_parsers.py +1 -0
  583. ansible_test/_internal/cli/parsers/key_value_parsers.py +1 -0
  584. ansible_test/_internal/cli/parsers/value_parsers.py +1 -0
  585. ansible_test/_internal/commands/__init__.py +1 -0
  586. ansible_test/_internal/commands/coverage/__init__.py +3 -2
  587. ansible_test/_internal/commands/coverage/analyze/__init__.py +1 -0
  588. ansible_test/_internal/commands/coverage/analyze/targets/__init__.py +1 -0
  589. ansible_test/_internal/commands/coverage/analyze/targets/combine.py +1 -0
  590. ansible_test/_internal/commands/coverage/analyze/targets/expand.py +1 -0
  591. ansible_test/_internal/commands/coverage/analyze/targets/filter.py +1 -0
  592. ansible_test/_internal/commands/coverage/analyze/targets/generate.py +1 -0
  593. ansible_test/_internal/commands/coverage/analyze/targets/missing.py +1 -0
  594. ansible_test/_internal/commands/coverage/combine.py +2 -1
  595. ansible_test/_internal/commands/coverage/erase.py +1 -0
  596. ansible_test/_internal/commands/coverage/html.py +1 -0
  597. ansible_test/_internal/commands/coverage/report.py +1 -0
  598. ansible_test/_internal/commands/coverage/xml.py +1 -0
  599. ansible_test/_internal/commands/env/__init__.py +2 -0
  600. ansible_test/_internal/commands/integration/__init__.py +22 -5
  601. ansible_test/_internal/commands/integration/cloud/__init__.py +1 -0
  602. ansible_test/_internal/commands/integration/cloud/acme.py +2 -1
  603. ansible_test/_internal/commands/integration/cloud/aws.py +1 -0
  604. ansible_test/_internal/commands/integration/cloud/azure.py +1 -0
  605. ansible_test/_internal/commands/integration/cloud/cs.py +1 -0
  606. ansible_test/_internal/commands/integration/cloud/digitalocean.py +1 -0
  607. ansible_test/_internal/commands/integration/cloud/galaxy.py +3 -2
  608. ansible_test/_internal/commands/integration/cloud/hcloud.py +1 -0
  609. ansible_test/_internal/commands/integration/cloud/httptester.py +3 -2
  610. ansible_test/_internal/commands/integration/cloud/nios.py +2 -1
  611. ansible_test/_internal/commands/integration/cloud/opennebula.py +1 -0
  612. ansible_test/_internal/commands/integration/cloud/openshift.py +1 -0
  613. ansible_test/_internal/commands/integration/cloud/scaleway.py +1 -0
  614. ansible_test/_internal/commands/integration/cloud/vcenter.py +1 -0
  615. ansible_test/_internal/commands/integration/cloud/vultr.py +1 -0
  616. ansible_test/_internal/commands/integration/coverage.py +8 -2
  617. ansible_test/_internal/commands/integration/filters.py +1 -0
  618. ansible_test/_internal/commands/integration/network.py +1 -0
  619. ansible_test/_internal/commands/integration/posix.py +1 -0
  620. ansible_test/_internal/commands/integration/windows.py +1 -0
  621. ansible_test/_internal/commands/sanity/__init__.py +19 -2
  622. ansible_test/_internal/commands/sanity/ansible_doc.py +1 -0
  623. ansible_test/_internal/commands/sanity/bin_symlinks.py +1 -0
  624. ansible_test/_internal/commands/sanity/compile.py +1 -0
  625. ansible_test/_internal/commands/sanity/ignores.py +1 -0
  626. ansible_test/_internal/commands/sanity/import.py +1 -0
  627. ansible_test/_internal/commands/sanity/integration_aliases.py +12 -0
  628. ansible_test/_internal/commands/sanity/pep8.py +1 -0
  629. ansible_test/_internal/commands/sanity/pslint.py +1 -0
  630. ansible_test/_internal/commands/sanity/pylint.py +25 -26
  631. ansible_test/_internal/commands/sanity/shellcheck.py +1 -0
  632. ansible_test/_internal/commands/sanity/validate_modules.py +1 -0
  633. ansible_test/_internal/commands/sanity/yamllint.py +1 -0
  634. ansible_test/_internal/commands/shell/__init__.py +44 -4
  635. ansible_test/_internal/commands/units/__init__.py +5 -1
  636. ansible_test/_internal/compat/__init__.py +1 -0
  637. ansible_test/_internal/compat/packaging.py +1 -0
  638. ansible_test/_internal/compat/yaml.py +1 -0
  639. ansible_test/_internal/completion.py +1 -0
  640. ansible_test/_internal/config.py +23 -13
  641. ansible_test/_internal/connections.py +1 -0
  642. ansible_test/_internal/constants.py +1 -0
  643. ansible_test/_internal/containers.py +1 -0
  644. ansible_test/_internal/content_config.py +1 -0
  645. ansible_test/_internal/core_ci.py +1 -0
  646. ansible_test/_internal/coverage_util.py +11 -10
  647. ansible_test/_internal/data.py +1 -0
  648. ansible_test/_internal/debugging.py +166 -0
  649. ansible_test/_internal/delegation.py +22 -13
  650. ansible_test/_internal/dev/__init__.py +1 -0
  651. ansible_test/_internal/dev/container_probe.py +1 -0
  652. ansible_test/_internal/diff.py +3 -2
  653. ansible_test/_internal/docker_util.py +2 -1
  654. ansible_test/_internal/encoding.py +1 -0
  655. ansible_test/_internal/executor.py +1 -0
  656. ansible_test/_internal/git.py +1 -0
  657. ansible_test/_internal/host_configs.py +1 -0
  658. ansible_test/_internal/host_profiles.py +260 -16
  659. ansible_test/_internal/http.py +1 -0
  660. ansible_test/_internal/init.py +1 -0
  661. ansible_test/_internal/inventory.py +39 -3
  662. ansible_test/_internal/io.py +1 -0
  663. ansible_test/_internal/metadata.py +95 -4
  664. ansible_test/_internal/payload.py +1 -0
  665. ansible_test/_internal/processes.py +80 -0
  666. ansible_test/_internal/provider/__init__.py +1 -0
  667. ansible_test/_internal/provider/layout/__init__.py +1 -0
  668. ansible_test/_internal/provider/layout/ansible.py +1 -0
  669. ansible_test/_internal/provider/layout/collection.py +1 -0
  670. ansible_test/_internal/provider/layout/unsupported.py +1 -0
  671. ansible_test/_internal/provider/source/__init__.py +1 -0
  672. ansible_test/_internal/provider/source/git.py +1 -0
  673. ansible_test/_internal/provider/source/installed.py +1 -0
  674. ansible_test/_internal/provider/source/unsupported.py +1 -0
  675. ansible_test/_internal/provider/source/unversioned.py +1 -0
  676. ansible_test/_internal/provisioning.py +11 -4
  677. ansible_test/_internal/pypi_proxy.py +6 -5
  678. ansible_test/_internal/python_requirements.py +28 -0
  679. ansible_test/_internal/ssh.py +2 -5
  680. ansible_test/_internal/target.py +9 -0
  681. ansible_test/_internal/test.py +3 -2
  682. ansible_test/_internal/thread.py +3 -1
  683. ansible_test/_internal/timeout.py +2 -1
  684. ansible_test/_internal/util.py +41 -12
  685. ansible_test/_internal/util_common.py +18 -5
  686. ansible_test/_internal/venv.py +1 -0
  687. ansible_test/_util/controller/sanity/code-smell/action-plugin-docs.py +1 -0
  688. ansible_test/_util/controller/sanity/code-smell/changelog/sphinx.py +1 -0
  689. ansible_test/_util/controller/sanity/code-smell/changelog.py +1 -0
  690. ansible_test/_util/controller/sanity/code-smell/empty-init.py +1 -0
  691. ansible_test/_util/controller/sanity/code-smell/line-endings.py +1 -0
  692. ansible_test/_util/controller/sanity/code-smell/no-assert.py +1 -0
  693. ansible_test/_util/controller/sanity/code-smell/no-get-exception.py +1 -0
  694. ansible_test/_util/controller/sanity/code-smell/no-illegal-filenames.py +1 -0
  695. ansible_test/_util/controller/sanity/code-smell/no-smart-quotes.py +1 -0
  696. ansible_test/_util/controller/sanity/code-smell/replace-urlopen.py +1 -0
  697. ansible_test/_util/controller/sanity/code-smell/runtime-metadata.py +28 -1
  698. ansible_test/_util/controller/sanity/code-smell/shebang.py +1 -0
  699. ansible_test/_util/controller/sanity/code-smell/symlinks.py +1 -0
  700. ansible_test/_util/controller/sanity/code-smell/use-argspec-type-path.py +1 -0
  701. ansible_test/_util/controller/sanity/code-smell/use-compat-six.py +1 -0
  702. ansible_test/_util/controller/sanity/integration-aliases/yaml_to_json.py +2 -1
  703. ansible_test/_util/controller/sanity/pep8/current-ignore.txt +4 -0
  704. ansible_test/_util/controller/sanity/pylint/config/ansible-test-target.cfg +8 -5
  705. ansible_test/_util/controller/sanity/pylint/config/ansible-test.cfg +8 -5
  706. ansible_test/_util/controller/sanity/pylint/config/code-smell.cfg +8 -5
  707. ansible_test/_util/controller/sanity/pylint/config/collection.cfg +4 -5
  708. ansible_test/_util/controller/sanity/pylint/config/default.cfg +8 -7
  709. ansible_test/_util/controller/sanity/pylint/plugins/deprecated_calls.py +541 -0
  710. ansible_test/_util/controller/sanity/pylint/plugins/deprecated_comment.py +137 -0
  711. ansible_test/_util/controller/sanity/pylint/plugins/hide_unraisable.py +1 -0
  712. ansible_test/_util/controller/sanity/pylint/plugins/string_format.py +1 -8
  713. ansible_test/_util/controller/sanity/pylint/plugins/unwanted.py +1 -8
  714. ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py +55 -28
  715. ansible_test/_util/controller/sanity/validate-modules/validate_modules/module_args.py +12 -5
  716. ansible_test/_util/controller/sanity/validate-modules/validate_modules/schema.py +13 -2
  717. ansible_test/_util/controller/sanity/validate-modules/validate_modules/utils.py +1 -0
  718. ansible_test/_util/controller/sanity/yamllint/yamllinter.py +35 -17
  719. ansible_test/_util/controller/tools/collection_detail.py +1 -0
  720. ansible_test/_util/controller/tools/yaml_to_json.py +2 -1
  721. ansible_test/_util/target/injector/python.py +8 -0
  722. ansible_test/_util/target/pytest/plugins/ansible_forked.py +6 -1
  723. ansible_test/_util/target/pytest/plugins/ansible_pytest_collections.py +2 -1
  724. ansible_test/_util/target/pytest/plugins/ansible_pytest_coverage.py +1 -0
  725. ansible_test/_util/target/sanity/compile/compile.py +1 -0
  726. ansible_test/_util/target/sanity/import/importer.py +15 -16
  727. ansible_test/_util/target/setup/bootstrap.sh +9 -20
  728. ansible_test/_util/target/setup/probe_cgroups.py +1 -0
  729. ansible_test/_util/target/setup/quiet_pip.py +1 -0
  730. ansible_test/_util/target/setup/requirements.py +38 -36
  731. ansible_test/_util/target/tools/virtualenvcheck.py +2 -1
  732. ansible_test/_util/target/tools/yamlcheck.py +2 -1
  733. ansible/compat/selectors.py +0 -32
  734. ansible/errors/yaml_strings.py +0 -138
  735. ansible/executor/action_write_locks.py +0 -44
  736. ansible/executor/discovery/python_target.py +0 -47
  737. ansible/executor/powershell/module_powershell_wrapper.ps1 +0 -86
  738. ansible/executor/powershell/module_script_wrapper.ps1 +0 -22
  739. ansible/module_utils/compat/importlib.py +0 -26
  740. ansible/module_utils/compat/selectors.py +0 -32
  741. ansible/module_utils/pycompat24.py +0 -73
  742. ansible/parsing/yaml/constructor.py +0 -178
  743. ansible/template/native_helpers.py +0 -251
  744. ansible/template/template.py +0 -43
  745. ansible/template/vars.py +0 -77
  746. ansible/utils/native_jinja.py +0 -11
  747. ansible/vars/fact_cache.py +0 -71
  748. ansible_core-2.18.7rc1.dist-info/RECORD +0 -992
  749. ansible_test/_util/controller/sanity/pylint/plugins/deprecated.py +0 -411
  750. {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/WHEEL +0 -0
  751. {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/entry_points.txt +0 -0
  752. {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/COPYING +0 -0
  753. {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/Apache-License.txt +0 -0
  754. {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/MIT-license.txt +0 -0
  755. {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/PSF-license.txt +0 -0
  756. {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/simplified_bsd.txt +0 -0
  757. {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/top_level.txt +0 -0
@@ -4,38 +4,67 @@
4
4
  from __future__ import annotations
5
5
 
6
6
  import base64
7
+ import dataclasses
7
8
  import errno
8
9
  import json
9
10
  import os
10
11
  import pkgutil
11
12
  import secrets
12
13
  import re
14
+ import typing as t
15
+
13
16
  from importlib import import_module
14
17
 
15
18
  from ansible.module_utils.compat.version import LooseVersion
16
19
 
17
20
  from ansible import constants as C
18
- from ansible.errors import AnsibleError
19
- from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text
21
+ from ansible.module_utils.common.json import Direction, get_module_encoder
22
+ from ansible.errors import AnsibleError, AnsibleFileNotFound
23
+ from ansible.module_utils.common.text.converters import to_bytes, to_text
24
+ from ansible.plugins.become import BecomeBase
25
+ from ansible.plugins.become.runas import BecomeModule as RunasBecomeModule
20
26
  from ansible.plugins.loader import ps_module_utils_loader
21
- from ansible.utils.collection_loader import resource_from_fqcr
27
+
28
+
29
+ @dataclasses.dataclass(frozen=True)
30
+ class _ExecManifest:
31
+ scripts: dict[str, _ScriptInfo] = dataclasses.field(default_factory=dict)
32
+ actions: list[_ManifestAction] = dataclasses.field(default_factory=list)
33
+ signed_hashlist: list[str] = dataclasses.field(default_factory=list)
34
+
35
+
36
+ @dataclasses.dataclass(frozen=True, kw_only=True)
37
+ class _ScriptInfo:
38
+ content: dataclasses.InitVar[bytes]
39
+ path: str
40
+ script: str = dataclasses.field(init=False)
41
+
42
+ def __post_init__(self, content: bytes) -> None:
43
+ object.__setattr__(self, 'script', base64.b64encode(content).decode())
44
+
45
+
46
+ @dataclasses.dataclass(frozen=True, kw_only=True)
47
+ class _ManifestAction:
48
+ name: str
49
+ params: dict[str, object] = dataclasses.field(default_factory=dict)
50
+ secure_params: dict[str, object] = dataclasses.field(default_factory=dict)
22
51
 
23
52
 
24
53
  class PSModuleDepFinder(object):
25
54
 
26
- def __init__(self):
55
+ def __init__(self) -> None:
27
56
  # This is also used by validate-modules to get a module's required utils in base and a collection.
28
- self.ps_modules = dict()
29
- self.exec_scripts = dict()
57
+ self.scripts: dict[str, _ScriptInfo] = {}
58
+ self.signed_hashlist: set[str] = set()
59
+
60
+ if builtin_hashlist := _get_powershell_signed_hashlist():
61
+ self.signed_hashlist.add(builtin_hashlist.path)
62
+ self.scripts[builtin_hashlist.path] = builtin_hashlist
30
63
 
31
- # by defining an explicit dict of cs utils and where they are used, we
32
- # can potentially save time by not adding the type multiple times if it
33
- # isn't needed
34
- self.cs_utils_wrapper = dict()
35
- self.cs_utils_module = dict()
64
+ self._util_deps: dict[str, set[str]] = {}
36
65
 
37
- self.ps_version = None
38
- self.os_version = None
66
+ self.ps_version: str | None = None
67
+ self.os_version: str | None = None
39
68
  self.become = False
40
69
 
41
70
  self._re_cs_module = [
@@ -70,36 +99,58 @@ class PSModuleDepFinder(object):
70
99
  r'(\.[\w\.]+))(?P<optional>\s+-Optional){0,1}')),
71
100
  ]
72
101
 
73
- self._re_wrapper = re.compile(to_bytes(r'(?i)^#\s*ansiblerequires\s+-wrapper\s+(\w*)'))
74
102
  self._re_ps_version = re.compile(to_bytes(r'(?i)^#requires\s+\-version\s+([0-9]+(\.[0-9]+){0,3})$'))
75
103
  self._re_os_version = re.compile(to_bytes(r'(?i)^#ansiblerequires\s+\-osversion\s+([0-9]+(\.[0-9]+){0,3})$'))
76
104
  self._re_become = re.compile(to_bytes(r'(?i)^#ansiblerequires\s+\-become$'))
77
105
 
78
- def scan_module(self, module_data, fqn=None, wrapper=False, powershell=True):
106
+ def scan_exec_script(self, name: str) -> None:
107
+ # scans lib/ansible/executor/powershell for scripts used in the module
108
+ # exec side. It also scans these scripts for any dependencies
109
+ if name in self.scripts:
110
+ return
111
+
112
+ exec_code = _get_powershell_script(name)
113
+ self.scripts[name] = _ScriptInfo(
114
+ content=exec_code,
115
+ path=name,
116
+ )
117
+ self.scan_module(exec_code, powershell=True)
118
+
119
+ def scan_module(
120
+ self,
121
+ module_data: bytes,
122
+ fqn: str | None = None,
123
+ powershell: bool = True,
124
+ ) -> set[str]:
79
125
  lines = module_data.split(b'\n')
80
- module_utils = set()
81
- if wrapper:
82
- cs_utils = self.cs_utils_wrapper
83
- else:
84
- cs_utils = self.cs_utils_module
126
+ module_utils: set[tuple[str, str, bool]] = set()
127
+
128
+ if fqn and fqn.startswith("ansible_collections."):
129
+ submodules = fqn.split('.')
130
+ collection_name = '.'.join(submodules[:3])
131
+
132
+ collection_hashlist = _get_powershell_signed_hashlist(collection_name)
133
+ if collection_hashlist and collection_hashlist.path not in self.signed_hashlist:
134
+ self.signed_hashlist.add(collection_hashlist.path)
135
+ self.scripts[collection_hashlist.path] = collection_hashlist
85
136
 
86
137
  if powershell:
87
138
  checks = [
88
139
  # PS module contains '#Requires -Module Ansible.ModuleUtils.*'
89
140
  # PS module contains '#AnsibleRequires -Powershell Ansible.*' (or collections module_utils ref)
90
- (self._re_ps_module, self.ps_modules, ".psm1"),
141
+ (self._re_ps_module, ".psm1"),
91
142
  # PS module contains '#AnsibleRequires -CSharpUtil Ansible.*' (or collections module_utils ref)
92
- (self._re_cs_in_ps_module, cs_utils, ".cs"),
143
+ (self._re_cs_in_ps_module, ".cs"),
93
144
  ]
94
145
  else:
95
146
  checks = [
96
147
  # CS module contains 'using Ansible.*;' or 'using ansible_collections.ns.coll.plugins.module_utils.*;'
97
- (self._re_cs_module, cs_utils, ".cs"),
148
+ (self._re_cs_module, ".cs"),
98
149
  ]
99
150
 
100
151
  for line in lines:
101
- for check in checks:
102
- for pattern in check[0]:
152
+ for patterns, util_extension in checks:
153
+ for pattern in patterns:
103
154
  match = pattern.match(line)
104
155
  if match:
105
156
  # tolerate windows line endings by stripping any remaining
@@ -107,82 +158,66 @@ class PSModuleDepFinder(object):
107
158
  module_util_name = to_text(match.group(1).rstrip())
108
159
  match_dict = match.groupdict()
109
160
  optional = match_dict.get('optional', None) is not None
110
-
111
- if module_util_name not in check[1].keys():
112
- module_utils.add((module_util_name, check[2], fqn, optional))
113
-
161
+ module_utils.add((module_util_name, util_extension, optional))
114
162
  break
115
163
 
116
- if powershell:
117
- ps_version_match = self._re_ps_version.match(line)
118
- if ps_version_match:
119
- self._parse_version_match(ps_version_match, "ps_version")
120
-
121
- os_version_match = self._re_os_version.match(line)
122
- if os_version_match:
123
- self._parse_version_match(os_version_match, "os_version")
124
-
125
- # once become is set, no need to keep on checking recursively
126
- if not self.become:
127
- become_match = self._re_become.match(line)
128
- if become_match:
129
- self.become = True
130
-
131
- if wrapper:
132
- wrapper_match = self._re_wrapper.match(line)
133
- if wrapper_match:
134
- self.scan_exec_script(wrapper_match.group(1).rstrip())
135
-
136
- # recursively drill into each Requires to see if there are any more
137
- # requirements
138
- for m in set(module_utils):
139
- self._add_module(*m, wrapper=wrapper)
140
-
141
- def scan_exec_script(self, name):
142
- # scans lib/ansible/executor/powershell for scripts used in the module
143
- # exec side. It also scans these scripts for any dependencies
144
- name = to_text(name)
145
- if name in self.exec_scripts.keys():
146
- return
147
-
148
- data = pkgutil.get_data("ansible.executor.powershell", to_native(name + ".ps1"))
149
- if data is None:
150
- raise AnsibleError("Could not find executor powershell script "
151
- "for '%s'" % name)
152
-
153
- b_data = to_bytes(data)
154
-
155
- # remove comments to reduce the payload size in the exec wrappers
156
- if C.DEFAULT_DEBUG:
157
- exec_script = b_data
158
- else:
159
- exec_script = _strip_comments(b_data)
160
- self.exec_scripts[name] = to_bytes(exec_script)
161
- self.scan_module(b_data, wrapper=True, powershell=True)
162
-
163
- def _add_module(self, name, ext, fqn, optional, wrapper=False):
164
- m = to_text(name)
165
-
166
- util_fqn = None
167
-
168
- if m.startswith("Ansible."):
169
- # Builtin util, use plugin loader to get the data
170
- mu_path = ps_module_utils_loader.find_plugin(m, ext)
171
-
172
- if not mu_path:
164
+ if not powershell:
165
+ continue
166
+
167
+ if ps_version_match := self._re_ps_version.match(line):
168
+ self._parse_version_match(ps_version_match, "ps_version")
169
+
170
+ if os_version_match := self._re_os_version.match(line):
171
+ self._parse_version_match(os_version_match, "os_version")
172
+
173
+ # once become is set, no need to keep on checking recursively
174
+ if not self.become and self._re_become.match(line):
175
+ self.become = True
176
+
177
+ dependencies: set[str] = set()
178
+ for name, ext, optional in set(module_utils):
179
+ util_name = self._scan_module_util(name, ext, fqn, optional)
180
+ if util_name:
181
+ dependencies.add(util_name)
182
+ util_deps = self._util_deps[util_name]
183
+ dependencies.update(util_deps)
184
+
185
+ return dependencies
186
+
187
+ def _scan_module_util(
188
+ self,
189
+ name: str,
190
+ ext: str,
191
+ module_fqn: str | None,
192
+ optional: bool,
193
+ ) -> str | None:
194
+ util_name: str
195
+ util_path: str
196
+ util_data: bytes
197
+ util_fqn: str | None = None
198
+
199
+ if name.startswith("Ansible."):
200
+ # Builtin util, or the old role module_utils reference.
201
+ util_name = f"{name}{ext}"
202
+
203
+ if util_name in self._util_deps:
204
+ return util_name
205
+
206
+ util_path = ps_module_utils_loader.find_plugin(name, ext)
207
+ if not util_path or not os.path.exists(util_path):
173
208
  if optional:
174
- return
209
+ return None
175
210
 
176
- raise AnsibleError('Could not find imported module support code '
177
- 'for \'%s\'' % m)
211
+ raise AnsibleError(f"Could not find imported module util '{name}'")
212
+
213
+ with open(util_path, 'rb') as mu_file:
214
+ util_data = mu_file.read()
178
215
 
179
- module_util_data = to_bytes(_slurp(mu_path))
180
216
  else:
181
217
  # Collection util, load the package data based on the util import.
182
-
183
- submodules = m.split(".")
184
- if m.startswith('.'):
185
- fqn_submodules = fqn.split('.')
218
+ submodules = name.split(".")
219
+ if name.startswith('.'):
220
+ fqn_submodules = (module_fqn or "").split('.')
186
221
  for submodule in submodules:
187
222
  if submodule:
188
223
  break
@@ -190,56 +225,70 @@ class PSModuleDepFinder(object):
190
225
 
191
226
  submodules = fqn_submodules + [s for s in submodules if s]
192
227
 
193
- n_package_name = to_native('.'.join(submodules[:-1]), errors='surrogate_or_strict')
194
- n_resource_name = to_native(submodules[-1] + ext, errors='surrogate_or_strict')
228
+ util_package = '.'.join(submodules[:-1])
229
+ util_resource_name = f"{submodules[-1]}{ext}"
230
+ util_fqn = f"{util_package}.{submodules[-1]}"
231
+ util_name = f"{util_package}.{util_resource_name}"
232
+
233
+ if util_name in self._util_deps:
234
+ return util_name
195
235
 
196
236
  try:
197
- module_util = import_module(n_package_name)
198
- pkg_data = pkgutil.get_data(n_package_name, n_resource_name)
199
- if pkg_data is None:
237
+ module_util = import_module(util_package)
238
+ util_code = pkgutil.get_data(util_package, util_resource_name)
239
+ if util_code is None:
200
240
  raise ImportError("No package data found")
201
-
202
- module_util_data = to_bytes(pkg_data, errors='surrogate_or_strict')
203
- util_fqn = to_text("%s.%s " % (n_package_name, submodules[-1]), errors='surrogate_or_strict')
241
+ util_data = util_code
204
242
 
205
243
  # Get the path of the util which is required for coverage collection.
206
244
  resource_paths = list(module_util.__path__)
207
245
  if len(resource_paths) != 1:
208
246
  # This should never happen with a collection but we are just being defensive about it.
209
- raise AnsibleError("Internal error: Referenced module_util package '%s' contains 0 or multiple "
210
- "import locations when we only expect 1." % n_package_name)
211
- mu_path = os.path.join(resource_paths[0], n_resource_name)
247
+ raise AnsibleError(f"Internal error: Referenced module_util package '{util_package}' contains 0 "
248
+ "or multiple import locations when we only expect 1.")
249
+
250
+ util_path = os.path.join(resource_paths[0], util_resource_name)
212
251
  except (ImportError, OSError) as err:
213
252
  if getattr(err, "errno", errno.ENOENT) == errno.ENOENT:
214
253
  if optional:
215
- return
254
+ return None
216
255
 
217
- raise AnsibleError('Could not find collection imported module support code for \'%s\''
218
- % to_native(m))
256
+ raise AnsibleError(f"Could not find collection imported module support code for '{name}'")
219
257
 
220
258
  else:
221
259
  raise
222
260
 
223
- util_info = {
224
- 'data': module_util_data,
225
- 'path': to_text(mu_path),
226
- }
227
- if ext == ".psm1":
228
- self.ps_modules[m] = util_info
229
- else:
230
- if wrapper:
231
- self.cs_utils_wrapper[m] = util_info
232
- else:
233
- self.cs_utils_module[m] = util_info
234
- self.scan_module(module_util_data, fqn=util_fqn, wrapper=wrapper, powershell=(ext == ".psm1"))
261
+ # This is important to be set before scan_module is called to avoid
262
+ # recursive dependencies.
263
+ self.scripts[util_name] = _ScriptInfo(
264
+ content=util_data,
265
+ path=util_path,
266
+ )
267
+
268
+ # It is important this is set before calling scan_module to ensure
269
+ # recursive dependencies don't result in an infinite loop.
270
+ dependencies = self._util_deps[util_name] = set()
271
+
272
+ util_deps = self.scan_module(util_data, fqn=util_fqn, powershell=(ext == ".psm1"))
273
+ dependencies.update(util_deps)
274
+ for dep in dependencies:
275
+ if dep_list := self._util_deps.get(dep):
276
+ dependencies.update(dep_list)
277
+
278
+ if ext == ".cs":
279
+ # Any C# code requires the AddType.psm1 module to load.
280
+ dependencies.add("Ansible.ModuleUtils.AddType.psm1")
281
+ self._scan_module_util("Ansible.ModuleUtils.AddType", ".psm1", None, False)
235
282
 
236
- def _parse_version_match(self, match, attribute):
283
+ return util_name
284
+
285
+ def _parse_version_match(self, match: re.Match, attribute: str) -> None:
237
286
  new_version = to_text(match.group(1)).rstrip()
238
287
 
239
288
  # PowerShell cannot cast a string of "1" to Version, it must have at
240
289
  # least the major.minor for it to be valid so we append 0
241
290
  if match.group(2) is None:
242
- new_version = "%s.0" % new_version
291
+ new_version = f"{new_version}.0"
243
292
 
244
293
  existing_version = getattr(self, attribute, None)
245
294
  if existing_version is None:
@@ -250,152 +299,307 @@ class PSModuleDepFinder(object):
250
299
  setattr(self, attribute, new_version)
251
300
 
252
301
 
253
- def _slurp(path):
254
- if not os.path.exists(path):
255
- raise AnsibleError("imported module support code does not exist at %s"
256
- % os.path.abspath(path))
257
- fd = open(path, 'rb')
258
- data = fd.read()
259
- fd.close()
260
- return data
261
-
262
-
263
- def _strip_comments(source):
264
- # Strip comments and blank lines from the wrapper
265
- buf = []
266
- start_block = False
267
- for line in source.splitlines():
268
- l = line.strip()
269
-
270
- if start_block and l.endswith(b'#>'):
271
- start_block = False
272
- continue
273
- elif start_block:
274
- continue
275
- elif l.startswith(b'<#'):
276
- start_block = True
277
- continue
278
- elif not l or l.startswith(b'#'):
279
- continue
280
-
281
- buf.append(line)
282
- return b'\n'.join(buf)
283
-
284
-
285
- def _create_powershell_wrapper(b_module_data, module_path, module_args,
286
- environment, async_timeout, become,
287
- become_method, become_user, become_password,
288
- become_flags, substyle, task_vars, module_fqn):
289
- # creates the manifest/wrapper used in PowerShell/C# modules to enable
290
- # things like become and async - this is also called in action/script.py
291
-
292
- # FUTURE: add process_wrapper.ps1 to run module_wrapper in a new process
293
- # if running under a persistent connection and substyle is C# so we
294
- # don't have type conflicts
302
+ def _bootstrap_powershell_script(
303
+ name: str,
304
+ parameters: dict[str, t.Any] | None = None,
305
+ *,
306
+ has_input: bool = False,
307
+ ) -> tuple[str, bytes]:
308
+ """Build bootstrap wrapper for specified script.
309
+
310
+ Builds the bootstrap wrapper and input needed to run the specified executor
311
+ PowerShell script specified.
312
+
313
+ :param name: The name of the PowerShell script to run.
314
+ :param parameters: The parameters to pass to the script.
315
+ :param has_input: The script will be provided with input data.
316
+ :return: The bootstrap wrapper and input to provide to it.
317
+ """
318
+ exec_manifest = _ExecManifest()
319
+
320
+ script = _get_powershell_script(name)
321
+ exec_manifest.scripts[name] = _ScriptInfo(
322
+ content=script,
323
+ path=name,
324
+ )
325
+
326
+ exec_manifest.actions.append(
327
+ _ManifestAction(
328
+ name=name,
329
+ params=parameters or {},
330
+ )
331
+ )
332
+
333
+ if hashlist := _get_powershell_signed_hashlist():
334
+ exec_manifest.signed_hashlist.append(hashlist.path)
335
+ exec_manifest.scripts[hashlist.path] = hashlist
336
+
337
+ bootstrap_wrapper = _get_powershell_script("bootstrap_wrapper.ps1")
338
+ bootstrap_input = _get_bootstrap_input(exec_manifest)
339
+ if has_input:
340
+ bootstrap_input += b"\n\0\0\0\0\n"
341
+
342
+ return bootstrap_wrapper.decode(), bootstrap_input
343
+
344
+
345
+ def _get_powershell_script(
346
+ name: str,
347
+ ) -> bytes:
348
+ """Get the requested PowerShell script.
349
+
350
+ Gets the script stored in the ansible.executore.powershell package.
351
+
352
+ :param name: The name of the PowerShell script to retrieve.
353
+ :return: The contents of the requested PowerShell script as a byte string.
354
+ """
355
+ package_name = 'ansible.executor.powershell'
356
+
357
+ code = pkgutil.get_data(package_name, name)
358
+ if code is None:
359
+ raise AnsibleFileNotFound(f"Could not find powershell script '{package_name}.{name}'")
360
+
361
+ try:
362
+ sig_data = pkgutil.get_data(package_name, f"{name}.authenticode")
363
+ except FileNotFoundError:
364
+ sig_data = None
365
+
366
+ if sig_data:
367
+ code = code + b"\r\n" + b"\r\n".join(sig_data.splitlines()) + b"\r\n"
368
+
369
+ return code
370
+
371
+
372
+ def _create_powershell_wrapper(
373
+ *,
374
+ name: str,
375
+ module_data: bytes,
376
+ module_path: str,
377
+ module_args: dict[t.Any, t.Any],
378
+ environment: dict[str, str],
379
+ async_timeout: int,
380
+ become_plugin: BecomeBase | None,
381
+ substyle: t.Literal["powershell", "script"],
382
+ task_vars: dict[str, t.Any],
383
+ profile: str,
384
+ ) -> bytes:
385
+ """Creates module or script wrapper for PowerShell.
386
+
387
+ Creates the input data to provide to bootstrap_wrapper.ps1 when running a
388
+ PowerShell module or script.
389
+
390
+ :param name: The fully qualified name of the module or script filename (without extension).
391
+ :param module_data: The data of the module or script.
392
+ :param module_path: The path of the module or script.
393
+ :param module_args: The arguments to pass to the module or script.
394
+ :param environment: The environment variables to set when running the module or script.
395
+ :param async_timeout: The timeout to use for async execution or 0 for no async.
396
+ :param become_plugin: The become plugin to use for privilege escalation or None for no become.
397
+ :param substyle: The substyle of the module or script to run [powershell or script].
398
+ :param task_vars: The task variables used on the task.
399
+
400
+ :return: The input data for bootstrap_wrapper.ps1 as a byte string.
401
+ """
402
+
403
+ actions: list[_ManifestAction] = []
295
404
  finder = PSModuleDepFinder()
296
- if substyle != 'script':
297
- # don't scan the module for util dependencies and other Ansible related
298
- # flags if the substyle is 'script' which is set by action/script
299
- finder.scan_module(b_module_data, fqn=module_fqn, powershell=(substyle == "powershell"))
300
-
301
- module_wrapper = "module_%s_wrapper" % substyle
302
- exec_manifest = dict(
303
- module_entry=to_text(base64.b64encode(b_module_data)),
304
- powershell_modules=dict(),
305
- csharp_utils=dict(),
306
- csharp_utils_module=list(), # csharp_utils only required by a module
307
- module_args=module_args,
308
- actions=[module_wrapper],
309
- environment=environment,
310
- encoded_output=False,
405
+ finder.scan_exec_script('module_wrapper.ps1')
406
+
407
+ ext = os.path.splitext(module_path)[1]
408
+ name_with_ext = f"{name}{ext}"
409
+ finder.scripts[name_with_ext] = _ScriptInfo(
410
+ content=module_data,
411
+ path=module_path,
311
412
  )
312
- finder.scan_exec_script(module_wrapper)
413
+
414
+ module_params: dict[str, t.Any] = {
415
+ 'Script': name_with_ext,
416
+ 'Environment': environment,
417
+ }
418
+ if substyle != 'script':
419
+ module_deps = finder.scan_module(
420
+ module_data,
421
+ fqn=name,
422
+ powershell=True,
423
+ )
424
+ cs_deps = []
425
+ ps_deps = []
426
+ for dep in module_deps:
427
+ if dep.endswith('.cs'):
428
+ cs_deps.append(dep)
429
+ else:
430
+ ps_deps.append(dep)
431
+
432
+ module_params |= {
433
+ 'Variables': [
434
+ {
435
+ 'Name': 'complex_args',
436
+ 'Value': _prepare_module_args(module_args, profile),
437
+ 'Scope': 'Global',
438
+ },
439
+ ],
440
+ 'CSharpModules': cs_deps,
441
+ 'PowerShellModules': ps_deps,
442
+ 'ForModule': True,
443
+ }
444
+
445
+ if become_plugin or finder.become:
446
+ become_script = 'become_wrapper.ps1'
447
+ become_params: dict[str, t.Any] = {
448
+ 'BecomeUser': 'SYSTEM',
449
+ }
450
+ become_secure_params: dict[str, t.Any] = {}
451
+
452
+ if become_plugin:
453
+ if not isinstance(become_plugin, RunasBecomeModule):
454
+ msg = f"Become plugin {become_plugin.name} is not supported by the Windows exec wrapper. Make sure to set the become method to runas."
455
+ raise AnsibleError(msg)
456
+
457
+ become_script, become_params, become_secure_params = become_plugin._build_powershell_wrapper_action()
458
+
459
+ finder.scan_exec_script('exec_wrapper.ps1')
460
+ finder.scan_exec_script(become_script)
461
+ actions.append(
462
+ _ManifestAction(
463
+ name=become_script,
464
+ params=become_params,
465
+ secure_params=become_secure_params,
466
+ )
467
+ )
313
468
 
314
469
  if async_timeout > 0:
315
- finder.scan_exec_script('exec_wrapper')
316
- finder.scan_exec_script('async_watchdog')
317
- finder.scan_exec_script('async_wrapper')
318
-
319
- exec_manifest["actions"].insert(0, 'async_watchdog')
320
- exec_manifest["actions"].insert(0, 'async_wrapper')
321
- exec_manifest["async_jid"] = f'j{secrets.randbelow(999999999999)}'
322
- exec_manifest["async_timeout_sec"] = async_timeout
323
- exec_manifest["async_startup_timeout"] = C.config.get_config_value("WIN_ASYNC_STARTUP_TIMEOUT", variables=task_vars)
324
-
325
- if become and resource_from_fqcr(become_method) == 'runas': # runas and namespace.collection.runas
326
- finder.scan_exec_script('exec_wrapper')
327
- finder.scan_exec_script('become_wrapper')
328
-
329
- exec_manifest["actions"].insert(0, 'become_wrapper')
330
- exec_manifest["become_user"] = become_user
331
- exec_manifest["become_password"] = become_password
332
- exec_manifest['become_flags'] = become_flags
333
-
334
- exec_manifest['min_ps_version'] = finder.ps_version
335
- exec_manifest['min_os_version'] = finder.os_version
336
- if finder.become and 'become_wrapper' not in exec_manifest['actions']:
337
- finder.scan_exec_script('exec_wrapper')
338
- finder.scan_exec_script('become_wrapper')
339
-
340
- exec_manifest['actions'].insert(0, 'become_wrapper')
341
- exec_manifest['become_user'] = 'SYSTEM'
342
- exec_manifest['become_password'] = None
343
- exec_manifest['become_flags'] = None
344
-
345
- coverage_manifest = dict(
346
- module_path=module_path,
347
- module_util_paths=dict(),
348
- output=None,
349
- )
470
+ finder.scan_exec_script('bootstrap_wrapper.ps1')
471
+ finder.scan_exec_script('exec_wrapper.ps1')
472
+
473
+ async_dir = environment.get('ANSIBLE_ASYNC_DIR', None)
474
+ if not async_dir:
475
+ raise AnsibleError("The environment variable 'ANSIBLE_ASYNC_DIR' is not set.")
476
+
477
+ finder.scan_exec_script('async_wrapper.ps1')
478
+ actions.append(
479
+ _ManifestAction(
480
+ name='async_wrapper.ps1',
481
+ params={
482
+ 'AsyncDir': async_dir,
483
+ 'AsyncJid': f'j{secrets.randbelow(999999999999)}',
484
+ 'StartupTimeout': C.config.get_config_value("WIN_ASYNC_STARTUP_TIMEOUT", variables=task_vars),
485
+ },
486
+ )
487
+ )
488
+
489
+ finder.scan_exec_script('async_watchdog.ps1')
490
+ actions.append(
491
+ _ManifestAction(
492
+ name='async_watchdog.ps1',
493
+ params={
494
+ 'Timeout': async_timeout,
495
+ },
496
+ )
497
+ )
498
+
350
499
  coverage_output = C.config.get_config_value('COVERAGE_REMOTE_OUTPUT', variables=task_vars)
351
500
  if coverage_output and substyle == 'powershell':
352
- finder.scan_exec_script('coverage_wrapper')
353
- coverage_manifest['output'] = coverage_output
354
-
355
- coverage_enabled = C.config.get_config_value('COVERAGE_REMOTE_PATHS', variables=task_vars)
356
- coverage_manifest['path_filter'] = coverage_enabled
357
-
358
- # make sure Ansible.ModuleUtils.AddType is added if any C# utils are used
359
- if len(finder.cs_utils_wrapper) > 0 or len(finder.cs_utils_module) > 0:
360
- finder._add_module(b"Ansible.ModuleUtils.AddType", ".psm1", None, False,
361
- wrapper=False)
362
-
363
- # exec_wrapper is only required to be part of the payload if using
364
- # become or async, to save on payload space we check if exec_wrapper has
365
- # already been added, and remove it manually if it hasn't later
366
- exec_required = "exec_wrapper" in finder.exec_scripts.keys()
367
- finder.scan_exec_script("exec_wrapper")
368
- # must contain an empty newline so it runs the begin/process/end block
369
- finder.exec_scripts["exec_wrapper"] += b"\n\n"
370
-
371
- exec_wrapper = finder.exec_scripts["exec_wrapper"]
372
- if not exec_required:
373
- finder.exec_scripts.pop("exec_wrapper")
374
-
375
- for name, data in finder.exec_scripts.items():
376
- b64_data = to_text(base64.b64encode(data))
377
- exec_manifest[name] = b64_data
378
-
379
- for name, data in finder.ps_modules.items():
380
- b64_data = to_text(base64.b64encode(data['data']))
381
- exec_manifest['powershell_modules'][name] = b64_data
382
- coverage_manifest['module_util_paths'][name] = data['path']
383
-
384
- cs_utils = {}
385
- for cs_util in [finder.cs_utils_wrapper, finder.cs_utils_module]:
386
- for name, data in cs_util.items():
387
- cs_utils[name] = data['data']
388
-
389
- for name, data in cs_utils.items():
390
- b64_data = to_text(base64.b64encode(data))
391
- exec_manifest['csharp_utils'][name] = b64_data
392
- exec_manifest['csharp_utils_module'] = list(finder.cs_utils_module.keys())
393
-
394
- # To save on the data we are sending across we only add the coverage info if coverage is being run
395
- if 'coverage_wrapper' in exec_manifest:
396
- exec_manifest['coverage'] = coverage_manifest
397
-
398
- b_json = to_bytes(json.dumps(exec_manifest))
399
- # delimit the payload JSON from the wrapper to keep sensitive contents out of scriptblocks (which can be logged)
400
- b_data = exec_wrapper + b'\0\0\0\0' + b_json
401
- return b_data
501
+ path_filter = C.config.get_config_value('COVERAGE_REMOTE_PATHS', variables=task_vars)
502
+
503
+ finder.scan_exec_script('coverage_wrapper.ps1')
504
+ actions.append(
505
+ _ManifestAction(
506
+ name='coverage_wrapper.ps1',
507
+ params={
508
+ 'ModuleName': name_with_ext,
509
+ 'OutputPath': coverage_output,
510
+ 'PathFilter': path_filter,
511
+ },
512
+ )
513
+ )
514
+
515
+ actions.append(
516
+ _ManifestAction(
517
+ name='module_wrapper.ps1',
518
+ params=module_params,
519
+ ),
520
+ )
521
+
522
+ temp_path: str | None = None
523
+ for temp_key in ['_ansible_tmpdir', '_ansible_remote_tmp']:
524
+ if temp_value := module_args.get(temp_key, None):
525
+ temp_path = temp_value
526
+ break
527
+
528
+ exec_manifest = _ExecManifest(
529
+ scripts=finder.scripts,
530
+ actions=actions,
531
+ signed_hashlist=list(finder.signed_hashlist),
532
+ )
533
+
534
+ return _get_bootstrap_input(
535
+ exec_manifest,
536
+ min_os_version=finder.os_version,
537
+ min_ps_version=finder.ps_version,
538
+ temp_path=temp_path,
539
+ )
540
+
541
+
542
+ def _get_bootstrap_input(
543
+ manifest: _ExecManifest,
544
+ min_os_version: str | None = None,
545
+ min_ps_version: str | None = None,
546
+ temp_path: str | None = None,
547
+ ) -> bytes:
548
+ """Gets the input for bootstrap_wrapper.ps1
549
+
550
+ Gets the input needed to send to bootstrap_wrapper.ps1 to run code through
551
+ exec_wrapper.ps1.
552
+
553
+ :param manifest: The exec wrapper manifest of scripts and actions to run.
554
+ :param min_os_version: The minimum OS version required to run the scripts.
555
+ :param min_ps_version: The minimum PowerShell version required to run the scripts.
556
+ :param temp_path: The temporary path to use for the scripts if needed.
557
+ :return: The input for bootstrap_wrapper.ps1 as a byte string.
558
+ """
559
+ bootstrap_manifest = {
560
+ 'name': 'exec_wrapper',
561
+ 'script': _get_powershell_script("exec_wrapper.ps1").decode(),
562
+ 'params': {
563
+ 'MinOSVersion': min_os_version,
564
+ 'MinPSVersion': min_ps_version,
565
+ 'TempPath': temp_path,
566
+ },
567
+ }
568
+
569
+ bootstrap_input = json.dumps(bootstrap_manifest, ensure_ascii=True)
570
+ exec_input = json.dumps(dataclasses.asdict(manifest))
571
+ return f"{bootstrap_input}\n\0\0\0\0\n{exec_input}".encode()
572
+
573
+
574
+ def _prepare_module_args(module_args: dict[str, t.Any], profile: str) -> dict[str, t.Any]:
575
+ """
576
+ Serialize the module args with the specified profile and deserialize them with the Python built-in JSON decoder.
577
+ This is used to facilitate serializing module args with a different encoder (profile) than is used for the manifest.
578
+ """
579
+ encoder = get_module_encoder(profile, Direction.CONTROLLER_TO_MODULE)
580
+
581
+ return json.loads(json.dumps(module_args, cls=encoder))
582
+
583
+
584
+ def _get_powershell_signed_hashlist(
585
+ collection: str | None = None,
586
+ ) -> _ScriptInfo | None:
587
+ """Gets the signed hashlist script stored in either the Ansible package or for
588
+ the collection specified.
589
+
590
+ :param collection: The collection namespace to get the signed hashlist for or None for the builtin.
591
+ :return: The _ScriptInfo payload of the signed hashlist script if found, None if not.
592
+ """
593
+ resource = 'ansible.config' if collection is None else f"{collection}.meta"
594
+ signature_file = 'powershell_signatures.psd1'
595
+
596
+ try:
597
+ sig_data = pkgutil.get_data(resource, signature_file)
598
+ except FileNotFoundError:
599
+ sig_data = None
600
+
601
+ if sig_data:
602
+ resource_path = f"{resource}.{signature_file}"
603
+ return _ScriptInfo(content=sig_data, path=resource_path)
604
+
605
+ return None