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
@@ -1,238 +1,717 @@
1
- # (c) 2018 Ansible Project
1
+ # (c) 2025 Ansible Project
2
2
  # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
3
3
 
4
+ using namespace System.Collections
5
+ using namespace System.Collections.Generic
6
+ using namespace System.Diagnostics.CodeAnalysis
7
+ using namespace System.IO
8
+ using namespace System.Linq
9
+ using namespace System.Management.Automation
10
+ using namespace System.Management.Automation.Language
11
+ using namespace System.Management.Automation.Security
12
+ using namespace System.Reflection
13
+ using namespace System.Security.Cryptography
14
+ using namespace System.Text
15
+
16
+ [SuppressMessageAttribute(
17
+ "PSUseCmdletCorrectly",
18
+ "",
19
+ Justification = "ConvertFrom-Json is being used in a steppable pipeline and works this way."
20
+ )]
21
+ [CmdletBinding()]
22
+ param (
23
+ [Parameter(ValueFromPipeline)]
24
+ [string]
25
+ $InputObject,
26
+
27
+ [Parameter()]
28
+ [IDictionary]
29
+ $Manifest,
30
+
31
+ [Parameter()]
32
+ [switch]
33
+ $EncodeInputOutput,
34
+
35
+ [Parameter()]
36
+ [Version]
37
+ $MinOSVersion,
38
+
39
+ [Parameter()]
40
+ [Version]
41
+ $MinPSVersion,
42
+
43
+ [Parameter()]
44
+ [string]
45
+ $TempPath,
46
+
47
+ [Parameter()]
48
+ [PSObject]
49
+ $ActionParameters
50
+ )
51
+
4
52
  begin {
5
- $DebugPreference = "Continue"
6
- $ProgressPreference = "SilentlyContinue"
53
+ $DebugPreference = "SilentlyContinue"
7
54
  $ErrorActionPreference = "Stop"
8
- Set-StrictMode -Version 2
9
-
10
- # common functions that are loaded in exec and module context, this is set
11
- # as a script scoped variable so async_watchdog and module_wrapper can
12
- # access the functions when creating their Runspaces
13
- $script:common_functions = {
14
- Function ConvertFrom-AnsibleJson {
15
- <#
16
- .SYNOPSIS
17
- Converts a JSON string to a Hashtable/Array in the fastest way
18
- possible. Unfortunately ConvertFrom-Json is still faster but outputs
19
- a PSCustomObject which is cumbersome for module consumption.
20
-
21
- .PARAMETER InputObject
22
- [String] The JSON string to deserialize.
23
- #>
24
- param(
25
- [Parameter(Mandatory = $true, Position = 0)][String]$InputObject
26
- )
27
-
28
- # we can use -AsHashtable to get PowerShell to convert the JSON to
29
- # a Hashtable and not a PSCustomObject. This was added in PowerShell
30
- # 6.0, fall back to a manual conversion for older versions
31
- $cmdlet = Get-Command -Name ConvertFrom-Json -CommandType Cmdlet
32
- if ("AsHashtable" -in $cmdlet.Parameters.Keys) {
33
- return , (ConvertFrom-Json -InputObject $InputObject -AsHashtable)
55
+ $ProgressPreference = "SilentlyContinue"
56
+
57
+ if ($PSCommandPath -and (Test-Path -LiteralPath $PSCommandPath)) {
58
+ Remove-Item -LiteralPath $PSCommandPath -Force
59
+ }
60
+
61
+ # Try and set the console encoding to UTF-8 allowing Ansible to read the
62
+ # output of the wrapper as UTF-8 bytes.
63
+ try {
64
+ [Console]::InputEncoding = [Console]::OutputEncoding = [UTF8Encoding]::new()
65
+ }
66
+ catch {
67
+ # PSRP will not have a console host so this will fail. The line here is
68
+ # to ignore sanity checks.
69
+ $null = $_
70
+ }
71
+
72
+ if ($MinOSVersion) {
73
+ [version]$actualOSVersion = (Get-Item -LiteralPath $env:SystemRoot\System32\kernel32.dll).VersionInfo.ProductVersion
74
+
75
+ if ($actualOSVersion -lt $MinOSVersion) {
76
+ @{
77
+ failed = $true
78
+ msg = "This module cannot run on this OS as it requires a minimum version of $MinOSVersion, actual was $actualOSVersion"
79
+ } | ConvertTo-Json -Compress
80
+ $Host.SetShouldExit(1)
81
+ return
82
+ }
83
+ }
84
+
85
+ if ($MinPSVersion) {
86
+ if ($PSVersionTable.PSVersion -lt $MinPSVersion) {
87
+ @{
88
+ failed = $true
89
+ msg = "This module cannot run as it requires a minimum PowerShell version of $MinPSVersion, actual was ""$($PSVersionTable.PSVersion)"""
90
+ } | ConvertTo-Json -Compress
91
+ $Host.SetShouldExit(1)
92
+ return
93
+ }
94
+ }
95
+
96
+ # $Script:AnsibleManifest = @{} # Defined in process/end.
97
+ $Script:AnsibleShouldConstrain = [SystemPolicy]::GetSystemLockdownPolicy() -eq 'Enforce'
98
+ $Script:AnsibleTrustedHashList = [HashSet[string]]::new([StringComparer]::OrdinalIgnoreCase)
99
+ $Script:AnsibleUnsupportedHashList = [HashSet[string]]::new([StringComparer]::OrdinalIgnoreCase)
100
+ $Script:AnsibleWrapperWarnings = [List[string]]::new()
101
+ $Script:AnsibleTempPath = @(
102
+ # Wrapper defined tmpdir
103
+ [Environment]::ExpandEnvironmentVariables($TempPath)
104
+ # Fallback to user's tmpdir
105
+ [Path]::GetTempPath()
106
+ # Should not happen but just in case use the current dir.
107
+ $pwd.Path
108
+ ) | Where-Object {
109
+ if (-not $_) {
110
+ return $false
111
+ }
112
+
113
+ try {
114
+ Test-Path -LiteralPath $_ -ErrorAction Ignore
115
+ }
116
+ catch {
117
+ # Access denied could cause Test-Path to throw an exception.
118
+ $false
119
+ }
120
+ } | Select-Object -First 1
121
+ $Script:AnsibleTempScripts = [List[string]]::new()
122
+ $Script:AnsibleClrFacadeSet = $false
123
+
124
+ Function Convert-JsonObject {
125
+ param(
126
+ [Parameter(Mandatory, ValueFromPipeline)]
127
+ [AllowNull()]
128
+ [object]
129
+ $InputObject
130
+ )
131
+
132
+ process {
133
+ # Using the full type name is important as PSCustomObject is an
134
+ # alias for PSObject which all piped objects are.
135
+ if ($InputObject -is [System.Management.Automation.PSCustomObject]) {
136
+ $value = @{}
137
+ foreach ($prop in $InputObject.PSObject.Properties) {
138
+ $value[$prop.Name] = Convert-JsonObject -InputObject $prop.Value
139
+ }
140
+ $value
141
+ }
142
+ elseif ($InputObject -is [Array]) {
143
+ , @($InputObject | Convert-JsonObject)
34
144
  }
35
145
  else {
36
- # get the PSCustomObject and then manually convert from there
37
- $raw_obj = ConvertFrom-Json -InputObject $InputObject
146
+ $InputObject
147
+ }
148
+ }
149
+ }
38
150
 
39
- Function ConvertTo-Hashtable {
40
- param($InputObject)
151
+ Function Get-AnsibleScript {
152
+ [CmdletBinding()]
153
+ param (
154
+ [Parameter(Mandatory)]
155
+ [string]
156
+ $Name,
41
157
 
42
- if ($null -eq $InputObject) {
43
- return $null
44
- }
158
+ [Parameter()]
159
+ [switch]
160
+ $IncludeScriptBlock,
45
161
 
46
- if ($InputObject -is [PSCustomObject]) {
47
- $new_value = @{}
48
- foreach ($prop in $InputObject.PSObject.Properties.GetEnumerator()) {
49
- $new_value.($prop.Name) = (ConvertTo-Hashtable -InputObject $prop.Value)
50
- }
51
- return , $new_value
52
- }
53
- elseif ($InputObject -is [Array]) {
54
- $new_value = [System.Collections.ArrayList]@()
55
- foreach ($val in $InputObject) {
56
- $new_value.Add((ConvertTo-Hashtable -InputObject $val)) > $null
57
- }
58
- return , $new_value.ToArray()
59
- }
60
- else {
61
- return , $InputObject
62
- }
162
+ [Parameter()]
163
+ [switch]
164
+ $SkipHashCheck
165
+ )
166
+
167
+ if (-not $Script:AnsibleManifest.scripts.Contains($Name)) {
168
+ $err = [ErrorRecord]::new(
169
+ [Exception]::new("Could not find the script '$Name'."),
170
+ "ScriptNotFound",
171
+ [ErrorCategory]::ObjectNotFound,
172
+ $Name)
173
+ $PSCmdlet.ThrowTerminatingError($err)
174
+ }
175
+
176
+ $scriptInfo = $Script:AnsibleManifest.scripts[$Name]
177
+ $scriptBytes = [Convert]::FromBase64String($scriptInfo.script)
178
+ $scriptContents = [Encoding]::UTF8.GetString($scriptBytes)
179
+
180
+ $sbk = $null
181
+ if ($IncludeScriptBlock) {
182
+ $sbk = [Parser]::ParseInput(
183
+ $scriptContents,
184
+ $Name,
185
+ [ref]$null,
186
+ [ref]$null).GetScriptBlock()
187
+ }
188
+
189
+ $outputValue = [PSCustomObject]@{
190
+ Name = $Name
191
+ Script = $scriptContents
192
+ Path = $scriptInfo.path
193
+ ScriptBlock = $sbk
194
+ ShouldConstrain = $false
195
+ }
196
+
197
+ if (-not $Script:AnsibleShouldConstrain) {
198
+ $outputValue
199
+ return
200
+ }
201
+
202
+ if (-not $SkipHashCheck) {
203
+ $sha256 = [SHA256]::Create()
204
+ $scriptHash = [BitConverter]::ToString($sha256.ComputeHash($scriptBytes)).Replace("-", "")
205
+ $sha256.Dispose()
206
+
207
+ if ($Script:AnsibleUnsupportedHashList.Contains($scriptHash)) {
208
+ $err = [ErrorRecord]::new(
209
+ [Exception]::new("Provided script for '$Name' is marked as unsupported in CLM mode."),
210
+ "ScriptUnsupported",
211
+ [ErrorCategory]::SecurityError,
212
+ $Name)
213
+ $PSCmdlet.ThrowTerminatingError($err)
214
+ }
215
+ elseif ($Script:AnsibleTrustedHashList.Contains($scriptHash)) {
216
+ $outputValue
217
+ return
218
+ }
219
+ }
220
+
221
+ # If we have reached here we are running in a locked down environment
222
+ # and the script is not trusted in the signed hashlists. Check if it
223
+ # contains the authenticode signature and verify that using PowerShell.
224
+ # [SystemPolicy]::GetFilePolicyEnforcement(...) is a new API but only
225
+ # present in Server 2025+ so we need to rely on the known behaviour of
226
+ # Get-Command to fail with CommandNotFoundException if the script is
227
+ # not allowed to run.
228
+ $outputValue.ShouldConstrain = $true
229
+ if ($scriptContents -like "*`r`n# SIG # Begin signature block`r`n*") {
230
+ Set-WinPSDefaultFileEncoding
231
+
232
+ # If the script is manually signed we need to ensure the signature
233
+ # is valid and trusted by the OS policy.
234
+ # We must use '.ps1' so the ExternalScript WDAC check will apply.
235
+ $tmpFile = [Path]::Combine($Script:AnsibleTempPath, "ansible-tmp-$([Guid]::NewGuid()).ps1")
236
+ try {
237
+ [File]::WriteAllBytes($tmpFile, $scriptBytes)
238
+ $cmd = Get-Command -Name $tmpFile -CommandType ExternalScript -ErrorAction Stop
239
+
240
+ # Get-Command caches the file contents after loading which we
241
+ # use to verify it was not modified before the signature check.
242
+ $expectedScript = $cmd.OriginalEncoding.GetString($scriptBytes)
243
+ if ($expectedScript -ne $cmd.ScriptContents) {
244
+ $err = [ErrorRecord]::new(
245
+ [Exception]::new("Script has been modified during signature check."),
246
+ "ScriptModifiedTrusted",
247
+ [ErrorCategory]::SecurityError,
248
+ $Name)
249
+ $PSCmdlet.ThrowTerminatingError($err)
63
250
  }
64
- return , (ConvertTo-Hashtable -InputObject $raw_obj)
65
- }
66
- }
67
-
68
- Function Format-AnsibleException {
69
- <#
70
- .SYNOPSIS
71
- Formats a PowerShell ErrorRecord to a string that's fit for human
72
- consumption.
73
-
74
- .NOTES
75
- Using Out-String can give us the first part of the exception but it
76
- also wraps the messages at 80 chars which is not ideal. We also
77
- append the ScriptStackTrace and the .NET StackTrace if present.
78
- #>
79
- param([System.Management.Automation.ErrorRecord]$ErrorRecord)
80
-
81
- $exception = @"
82
- $($ErrorRecord.ToString())
83
- $($ErrorRecord.InvocationInfo.PositionMessage)
84
- + CategoryInfo : $($ErrorRecord.CategoryInfo.ToString())
85
- + FullyQualifiedErrorId : $($ErrorRecord.FullyQualifiedErrorId.ToString())
86
- "@
87
- # module_common strip comments and empty newlines, need to manually
88
- # add a preceding newline using `r`n
89
- $exception += "`r`n`r`nScriptStackTrace:`r`n$($ErrorRecord.ScriptStackTrace)`r`n"
90
-
91
- # exceptions from C# will also have a StackTrace which we
92
- # append if found
93
- if ($null -ne $ErrorRecord.Exception.StackTrace) {
94
- $exception += "`r`n$($ErrorRecord.Exception.ToString())"
95
- }
96
-
97
- return $exception
98
- }
99
- }
100
- .$common_functions
101
-
102
- # common wrapper functions used in the exec wrappers, this is defined in a
103
- # script scoped variable so async_watchdog can pass them into the async job
104
- $script:wrapper_functions = {
105
- Function Write-AnsibleError {
106
- <#
107
- .SYNOPSIS
108
- Writes an error message to a JSON string in the format that Ansible
109
- understands. Also optionally adds an exception record if the
110
- ErrorRecord is passed through.
111
- #>
112
- param(
113
- [Parameter(Mandatory = $true)][String]$Message,
114
- [System.Management.Automation.ErrorRecord]$ErrorRecord = $null
115
- )
116
- $result = @{
117
- msg = $Message
118
- failed = $true
251
+
252
+ $outputValue.ShouldConstrain = $false
253
+ }
254
+ catch [CommandNotFoundException] {
255
+ $null = $null # No-op but satisfies the linter.
256
+ }
257
+ finally {
258
+ if (Test-Path -LiteralPath $tmpFile) {
259
+ Remove-Item -LiteralPath $tmpFile -Force
260
+ }
261
+ }
262
+ }
263
+
264
+ if ($outputValue.ShouldConstrain -and $IncludeScriptBlock) {
265
+ # If the script is untrusted and a scriptblock was requested we
266
+ # error out as the sbk would have run in FLM.
267
+ $err = [ErrorRecord]::new(
268
+ [Exception]::new("Provided script for '$Name' is not trusted to run."),
269
+ "ScriptNotTrusted",
270
+ [ErrorCategory]::SecurityError,
271
+ $Name)
272
+ $PSCmdlet.ThrowTerminatingError($err)
273
+ }
274
+ else {
275
+ $outputValue
276
+ }
277
+ }
278
+
279
+ Function Get-NextAnsibleAction {
280
+ [CmdletBinding()]
281
+ param ()
282
+
283
+ $action, $newActions = $Script:AnsibleManifest.actions
284
+ $Script:AnsibleManifest.actions = @($newActions | Select-Object)
285
+
286
+ $actionName = $action.name
287
+ $actionParams = $action.params
288
+ $actionScript = Get-AnsibleScript -Name $actionName -IncludeScriptBlock
289
+
290
+ foreach ($kvp in $action.secure_params.GetEnumerator()) {
291
+ if (-not $kvp.Value) {
292
+ continue
119
293
  }
120
- if ($null -ne $ErrorRecord) {
121
- $result.msg += ": $($ErrorRecord.Exception.Message)"
122
- $result.exception = (Format-AnsibleException -ErrorRecord $ErrorRecord)
123
- }
124
- Write-Output -InputObject (ConvertTo-Json -InputObject $result -Depth 99 -Compress)
125
- }
126
-
127
- Function Write-AnsibleLog {
128
- <#
129
- .SYNOPSIS
130
- Used as a debugging tool to log events to a file as they run in the
131
- exec wrappers. By default this is a noop function but the $log_path
132
- can be manually set to enable it. Manually set ANSIBLE_EXEC_DEBUG as
133
- an env value on the Windows host that this is run on to enable.
134
- #>
135
- param(
136
- [Parameter(Mandatory = $true, Position = 0)][String]$Message,
137
- [Parameter(Position = 1)][String]$Wrapper
138
- )
139
-
140
- $log_path = $env:ANSIBLE_EXEC_DEBUG
141
- if ($log_path) {
142
- $log_path = [System.Environment]::ExpandEnvironmentVariables($log_path)
143
- $parent_path = [System.IO.Path]::GetDirectoryName($log_path)
144
- if (Test-Path -LiteralPath $parent_path -PathType Container) {
145
- $msg = "{0:u} - {1} - {2} - " -f (Get-Date), $pid, ([System.Security.Principal.WindowsIdentity]::GetCurrent().Name)
146
- if ($null -ne $Wrapper) {
147
- $msg += "$Wrapper - "
294
+
295
+ $name = $kvp.Key
296
+ $actionParams.$name = $kvp.Value | ConvertTo-SecureString -AsPlainText -Force
297
+ }
298
+
299
+ [PSCustomObject]@{
300
+ Name = $actionName
301
+ ScriptBlock = $actionScript.ScriptBlock
302
+ Parameters = $actionParams
303
+ }
304
+ }
305
+
306
+ Function Get-AnsibleExecWrapper {
307
+ [CmdletBinding()]
308
+ param (
309
+ [Parameter()]
310
+ [switch]
311
+ $ManifestAsParam,
312
+
313
+ [Parameter()]
314
+ [switch]
315
+ $EncodeInputOutput,
316
+
317
+ [Parameter()]
318
+ [switch]
319
+ $IncludeScriptBlock
320
+ )
321
+
322
+ $scriptInfo = Get-AnsibleScript -Name exec_wrapper.ps1 -IncludeScriptBlock:$IncludeScriptBlock
323
+ $params = @{
324
+ # TempPath may contain env vars that change based on the runtime
325
+ # environment. Ensure we use that and not the $script:AnsibleTempPath
326
+ # when starting the exec wrapper.
327
+ TempPath = $TempPath
328
+ EncodeInputOutput = $EncodeInputOutput.IsPresent
329
+ }
330
+
331
+ $inputData = $null
332
+ if ($ManifestAsParam) {
333
+ $params.Manifest = $Script:AnsibleManifest
334
+ }
335
+ else {
336
+ $inputData = ConvertTo-Json -InputObject $Script:AnsibleManifest -Depth 99 -Compress
337
+ if ($EncodeInputOutput) {
338
+ $inputData = [Convert]::ToBase64String([Encoding]::UTF8.GetBytes($inputData))
339
+ }
340
+ }
341
+
342
+ [PSCustomObject]@{
343
+ ScriptInfo = $scriptInfo
344
+ Parameters = $params
345
+ InputData = $inputData
346
+ }
347
+ }
348
+
349
+ Function Import-PowerShellUtil {
350
+ [CmdletBinding()]
351
+ param (
352
+ [Parameter(Mandatory)]
353
+ [string[]]
354
+ $Name
355
+ )
356
+
357
+ foreach ($moduleName in $Name) {
358
+ $moduleInfo = Get-AnsibleScript -Name $moduleName -IncludeScriptBlock
359
+ $moduleShortName = [Path]::GetFileNameWithoutExtension($moduleName)
360
+ $null = New-Module -Name $moduleShortName -ScriptBlock $moduleInfo.ScriptBlock |
361
+ Import-Module -Scope Global
362
+ }
363
+ }
364
+
365
+ Function Import-CSharpUtil {
366
+ [CmdletBinding()]
367
+ param (
368
+ [Parameter(Mandatory)]
369
+ [string[]]
370
+ $Name
371
+ )
372
+
373
+ Import-PowerShellUtil -Name Ansible.ModuleUtils.AddType.psm1
374
+
375
+ $isBasicUtil = $false
376
+ $csharpModules = foreach ($moduleName in $Name) {
377
+ $scriptInfo = Get-AnsibleScript -Name $moduleName
378
+
379
+ if ($scriptInfo.ShouldConstrain) {
380
+ throw "C# module util '$Name' is not trusted and cannot be loaded."
381
+ }
382
+ if ($moduleName -eq 'Ansible.Basic.cs') {
383
+ $isBasicUtil = $true
384
+ }
385
+
386
+ $scriptInfo.Script
387
+ }
388
+
389
+ $fakeModule = [PSCustomObject]@{
390
+ Tmpdir = $Script:AnsibleTempPath
391
+ }
392
+ $warningFunc = [PSScriptMethod]::new('Warn', {
393
+ param($message)
394
+ $Script:AnsibleWrapperWarnings.Add($message)
395
+ })
396
+ $fakeModule.PSObject.Members.Add($warningFunc)
397
+ Add-CSharpType -References $csharpModules -AnsibleModule $fakeModule
398
+
399
+ if ($isBasicUtil) {
400
+ # Ansible.Basic.cs is a special case where we need to provide it
401
+ # with the wrapper warnings list so it injects it into the result.
402
+ [Ansible.Basic.AnsibleModule]::_WrapperWarnings = $Script:AnsibleWrapperWarnings
403
+ }
404
+ }
405
+
406
+ Function Import-SignedHashList {
407
+ [CmdletBinding()]
408
+ param (
409
+ [Parameter(Mandatory, ValueFromPipeline)]
410
+ [string]
411
+ $Name
412
+ )
413
+
414
+ process {
415
+ try {
416
+ # We skip the hash check to ensure we verify based on the
417
+ # authenticode signature and not whether it's trusted by an
418
+ # existing signed hash list.
419
+ $scriptInfo = Get-AnsibleScript -Name $Name -SkipHashCheck
420
+ if ($scriptInfo.ShouldConstrain) {
421
+ throw "script is not signed or not trusted to run."
422
+ }
423
+
424
+ $hashListAst = [Parser]::ParseInput(
425
+ $scriptInfo.Script,
426
+ $Name,
427
+ [ref]$null,
428
+ [ref]$null)
429
+ $manifestAst = $hashListAst.Find({ $args[0] -is [HashtableAst] }, $false)
430
+ if ($null -eq $manifestAst) {
431
+ throw "expecting a single hashtable in the signed manifest."
432
+ }
433
+
434
+ $out = $manifestAst.SafeGetValue()
435
+ if (-not $out.Contains('Version')) {
436
+ throw "expecting hash list to contain 'Version' key."
437
+ }
438
+ if ($out.Version -ne 1) {
439
+ throw "unsupported hash list Version $($out.Version), expecting 1."
440
+ }
441
+
442
+ if (-not $out.Contains('HashList')) {
443
+ throw "expecting hash list to contain 'HashList' key."
444
+ }
445
+
446
+ $out.HashList | ForEach-Object {
447
+ if ($_ -isnot [hashtable] -or -not $_.ContainsKey('Hash') -or $_.Hash -isnot [string] -or $_.Hash.Length -ne 64) {
448
+ throw "expecting hash list to contain hashtable with Hash key with a value of a SHA256 strings."
148
449
  }
149
- $msg += $Message + "`r`n"
150
- $msg_bytes = [System.Text.Encoding]::UTF8.GetBytes($msg)
151
450
 
152
- $fs = [System.IO.File]::Open($log_path, [System.IO.FileMode]::Append,
153
- [System.IO.FileAccess]::Write, [System.IO.FileShare]::ReadWrite)
154
- try {
155
- $fs.Write($msg_bytes, 0, $msg_bytes.Length)
451
+ if ($_.Mode -eq 'Trusted') {
452
+ $null = $Script:AnsibleTrustedHashList.Add($_.Hash)
453
+ }
454
+ elseif ($_.Mode -eq 'Unsupported') {
455
+ # Allows us to provide a better error when trying to run
456
+ # something in CLM that is marked as unsupported.
457
+ $null = $Script:AnsibleUnsupportedHashList.Add($_.Hash)
156
458
  }
157
- finally {
158
- $fs.Close()
459
+ else {
460
+ throw "expecting hash list entry for $($_.Hash) to contain a mode of 'Trusted' or 'Unsupported' but got '$($_.Mode)'."
159
461
  }
160
462
  }
161
463
  }
464
+ catch {
465
+ $_.ErrorDetails = [ErrorDetails]::new("Failed to process signed manifest '$Name': $_")
466
+ $PSCmdlet.WriteError($_)
467
+ }
162
468
  }
163
469
  }
164
- .$wrapper_functions
165
470
 
166
- # only init and stream in $json_raw if it wasn't set by the enclosing scope
167
- if (-not $(Get-Variable "json_raw" -ErrorAction SilentlyContinue)) {
168
- $json_raw = ''
471
+ Function New-TempAnsibleFile {
472
+ [OutputType([string])]
473
+ [CmdletBinding()]
474
+ param (
475
+ [Parameter(Mandatory)]
476
+ [string]
477
+ $FileName,
478
+
479
+ [Parameter(Mandatory)]
480
+ [string]
481
+ $Content
482
+ )
483
+
484
+ $name = [Path]::GetFileNameWithoutExtension($FileName)
485
+ $ext = [Path]::GetExtension($FileName)
486
+ $newName = "$($name)-$([Guid]::NewGuid())$ext"
487
+
488
+ $path = Join-Path -Path $Script:AnsibleTempPath $newName
489
+ Set-WinPSDefaultFileEncoding
490
+ [File]::WriteAllText($path, $Content, [UTF8Encoding]::new($false))
491
+
492
+ $path
169
493
  }
170
- } process {
171
- $json_raw += [String]$input
172
- } end {
173
- Write-AnsibleLog "INFO - starting exec_wrapper" "exec_wrapper"
174
- if (-not $json_raw) {
175
- Write-AnsibleError -Message "internal error: no input given to PowerShell exec wrapper"
176
- exit 1
494
+
495
+ Function Set-WinPSDefaultFileEncoding {
496
+ [CmdletBinding()]
497
+ param ()
498
+
499
+ # WinPS defaults to the locale encoding when loading a script from the
500
+ # file path but in Ansible we expect it to always be UTF-8 without a
501
+ # BOM. This lazily sets an internal field so pwsh reads it as UTF-8.
502
+ # If we don't do this then scripts saved as UTF-8 on the Ansible
503
+ # controller will not run as expected.
504
+ if ($PSVersionTable.PSVersion -lt '6.0' -and -not $Script:AnsibleClrFacadeSet) {
505
+ $clrFacade = [PSObject].Assembly.GetType('System.Management.Automation.ClrFacade')
506
+ $defaultEncodingField = $clrFacade.GetField('_defaultEncoding', [BindingFlags]'NonPublic, Static')
507
+ $defaultEncodingField.SetValue($null, [UTF8Encoding]::new($false))
508
+ $Script:AnsibleClrFacadeSet = $true
509
+ }
510
+ }
511
+
512
+ Function Write-AnsibleErrorJson {
513
+ [CmdletBinding()]
514
+ param (
515
+ [Parameter(Mandatory)]
516
+ [ErrorRecord]
517
+ $ErrorRecord,
518
+
519
+ [Parameter()]
520
+ [string]
521
+ $Message = "failure during exec_wrapper"
522
+ )
523
+
524
+ $exception = @(
525
+ "$ErrorRecord"
526
+ "$($ErrorRecord.InvocationInfo.PositionMessage)"
527
+ "+ CategoryInfo : $($ErrorRecord.CategoryInfo)"
528
+ "+ FullyQualifiedErrorId : $($ErrorRecord.FullyQualifiedErrorId)"
529
+ ""
530
+ "ScriptStackTrace:"
531
+ "$($ErrorRecord.ScriptStackTrace)"
532
+
533
+ if ($ErrorRecord.Exception.StackTrace) {
534
+ "$($ErrorRecord.Exception.StackTrace)"
535
+ }
536
+ ) -join ([Environment]::NewLine)
537
+
538
+ @{
539
+ failed = $true
540
+ msg = "${Message}: $ErrorRecord"
541
+ exception = $exception
542
+ } | ConvertTo-Json -Compress
543
+ $host.SetShouldExit(1)
177
544
  }
178
545
 
179
- Write-AnsibleLog "INFO - converting json raw to a payload" "exec_wrapper"
180
- $payload = ConvertFrom-AnsibleJson -InputObject $json_raw
181
- $payload.module_args._ansible_exec_wrapper_warnings = [System.Collections.Generic.List[string]]@()
546
+ Function Write-PowerShellClixmlStderr {
547
+ [CmdletBinding()]
548
+ param (
549
+ [Parameter(Mandatory)]
550
+ [AllowEmptyString()]
551
+ [string]
552
+ $Output
553
+ )
554
+
555
+ if (-not $Output) {
556
+ return
557
+ }
182
558
 
183
- # TODO: handle binary modules
184
- # TODO: handle persistence
559
+ # -EncodedCommand in WinPS will output CLIXML to stderr. This attempts to parse
560
+ # it into a human readable format otherwise it'll just output the raw CLIXML.
561
+ $wroteStderr = $false
562
+ if ($Output.StartsWith('#< CLIXML')) {
563
+ $clixml = $Output -split "\r?\n"
564
+ if ($clixml.Count -eq 2) {
565
+ try {
566
+ # PSSerialize.Deserialize doesn't tell us what streams each record
567
+ # is for so we get the S attribute manually.
568
+ $streams = @(([xml]$clixml[1]).Objs.GetEnumerator() | ForEach-Object { $_.S })
569
+ $objects = @([PSSerializer]::Deserialize($clixml[1]))
185
570
 
186
- if ($payload.min_os_version) {
187
- $min_os_version = [Version]$payload.min_os_version
188
- # Environment.OSVersion.Version is deprecated and may not return the
189
- # right version
190
- $actual_os_version = [Version](Get-Item -Path $env:SystemRoot\System32\kernel32.dll).VersionInfo.ProductVersion
571
+ for ($i = 0; $i -lt $objects.Count; $i++) {
572
+ $msg = $objects[$i]
573
+ if ($msg -isnot [string] -or $streams.Length -le $i) {
574
+ continue
575
+ }
191
576
 
192
- Write-AnsibleLog "INFO - checking if actual os version '$actual_os_version' is less than the min os version '$min_os_version'" "exec_wrapper"
193
- if ($actual_os_version -lt $min_os_version) {
194
- $msg = "internal error: This module cannot run on this OS as it requires a minimum version of $min_os_version, actual was $actual_os_version"
195
- Write-AnsibleError -Message $msg
196
- exit 1
577
+ # Doesn't use TrimEnd() so it only removes the last newline
578
+ if ($msg.EndsWith([Environment]::NewLine)) {
579
+ $msg = $msg.Substring(0, $msg.Length - [Environment]::NewLine.Length)
580
+ }
581
+ $stream = $streams[$i]
582
+ switch ($stream) {
583
+ 'error' { $host.UI.WriteErrorLine($msg) }
584
+ 'debug' { $host.UI.WriteDebugLine($msg) }
585
+ 'verbose' { $host.UI.WriteVerboseLine($msg) }
586
+ 'warning' { $host.UI.WriteWarningLine($msg) }
587
+ }
588
+ }
589
+ $wroteStderr = $true
590
+ }
591
+ catch {
592
+ $null = $_
593
+ }
594
+ }
595
+ }
596
+ if (-not $wroteStderr) {
597
+ $host.UI.WriteErrorLine($Output.TrimEnd())
197
598
  }
198
599
  }
199
- if ($payload.min_ps_version) {
200
- $min_ps_version = [Version]$payload.min_ps_version
201
- $actual_ps_version = $PSVersionTable.PSVersion
202
600
 
203
- Write-AnsibleLog "INFO - checking if actual PS version '$actual_ps_version' is less than the min PS version '$min_ps_version'" "exec_wrapper"
204
- if ($actual_ps_version -lt $min_ps_version) {
205
- $msg = "internal error: This module cannot run as it requires a minimum PowerShell version of $min_ps_version, actual was $actual_ps_version"
206
- Write-AnsibleError -Message $msg
207
- exit 1
601
+ # To handle optional input for the incoming manifest and optional input to
602
+ # the subsequent action we optionally run this step in the begin or end
603
+ # block.
604
+ $jsonPipeline = $null
605
+ $actionPipeline = $null
606
+ $setupManifest = {
607
+ [CmdletBinding()]
608
+ param (
609
+ [Parameter()]
610
+ [switch]
611
+ $ExpectingInput
612
+ )
613
+
614
+ if ($jsonPipeline) {
615
+ $Script:AnsibleManifest = $jsonPipeline.End()[0]
616
+ $jsonPipeline.Dispose()
617
+ $jsonPipeline = $null
618
+ }
619
+ else {
620
+ $Script:AnsibleManifest = $Manifest
621
+ }
622
+
623
+ if ($Script:AnsibleShouldConstrain) {
624
+ $Script:AnsibleManifest.signed_hashlist | Import-SignedHashList
625
+ }
626
+
627
+ $actionInfo = Get-NextAnsibleAction
628
+ $actionParams = $actionInfo.Parameters
629
+
630
+ if ($ActionParameters) {
631
+ foreach ($prop in $ActionParameters.PSObject.Properties) {
632
+ $actionParams[$prop.Name] = $prop.Value
633
+ }
634
+ }
635
+
636
+ $actionPipeline = { & $actionInfo.ScriptBlock @actionParams }.GetSteppablePipeline()
637
+ $actionPipeline.Begin($ExpectingInput)
638
+ if (-not $ExpectingInput) {
639
+ $null = $actionPipeline.Process()
208
640
  }
209
641
  }
210
642
 
211
- # pop 0th action as entrypoint
212
- $action = $payload.actions[0]
213
- Write-AnsibleLog "INFO - running action $action" "exec_wrapper"
643
+ try {
644
+ if ($Manifest) {
645
+ # If the manifest was provided through the parameter, we can start the
646
+ # action pipeline and all subsequent input (if any) will be sent to the
647
+ # action.
648
+ # It is important that $setupManifest is called by dot sourcing or
649
+ # else the pipelines started in it loose access to all parent scopes.
650
+ # https://github.com/PowerShell/PowerShell/issues/17868
651
+ . $setupManifest -ExpectingInput:$MyInvocation.ExpectingInput
652
+ }
653
+ else {
654
+ # Otherwise the first part of the input is the manifest json with the
655
+ # chance for extra data afterwards.
656
+ $jsonPipeline = { ConvertFrom-Json | Convert-JsonObject }.GetSteppablePipeline()
657
+ $jsonPipeline.Begin($true)
658
+ }
659
+ }
660
+ catch {
661
+ Write-AnsibleErrorJson -ErrorRecord $_
662
+ }
663
+ }
214
664
 
215
- $entrypoint = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($payload.($action)))
216
- $entrypoint = [ScriptBlock]::Create($entrypoint)
217
- # so we preserve the formatting and don't fall prey to locale issues, some
218
- # wrappers want the output to be in base64 form, we store the value here in
219
- # case the wrapper changes the value when they create a payload for their
220
- # own exec_wrapper
221
- $encoded_output = $payload.encoded_output
665
+ process {
666
+ try {
667
+ if ($actionPipeline) {
668
+ # We received our manifest and started the action pipeline, redirect
669
+ # all further input to that pipeline.
670
+ $null = $actionPipeline.Process($InputObject)
671
+ }
672
+ elseif ([string]::Equals($InputObject, "`0`0`0`0")) {
673
+ # Special marker used to indicate all subsequent input is for the
674
+ # action. Setup that pipeline and finalise the manifest.
675
+ . $setupManifest -ExpectingInput
676
+ }
677
+ elseif ($jsonPipeline) {
678
+ # Data is for the JSON manifest, decode if needed.
679
+ if ($EncodeInputOutput) {
680
+ $jsonPipeline.Process([Encoding]::UTF8.GetString([Convert]::FromBase64String($InputObject)))
681
+ }
682
+ else {
683
+ $jsonPipeline.Process($InputObject)
684
+ }
685
+ }
686
+ }
687
+ catch {
688
+ Write-AnsibleErrorJson -ErrorRecord $_
689
+ }
690
+ }
222
691
 
692
+ end {
223
693
  try {
224
- $output = &$entrypoint -Payload $payload
225
- if ($encoded_output -and $null -ne $output) {
226
- $b64_output = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($output))
227
- Write-Output -InputObject $b64_output
694
+ if ($jsonPipeline) {
695
+ # Only manifest input was received, process it now and start the
696
+ # action pipeline with no input being provided.
697
+ . $setupManifest
698
+ }
699
+
700
+ $out = $actionPipeline.End()
701
+ if ($EncodeInputOutput) {
702
+ [Convert]::ToBase64String([Encoding]::UTF8.GetBytes($out))
228
703
  }
229
704
  else {
230
- $output
705
+ $out
231
706
  }
232
707
  }
233
708
  catch {
234
- Write-AnsibleError -Message "internal error: failed to run exec_wrapper action $action" -ErrorRecord $_
235
- exit 1
709
+ Write-AnsibleErrorJson -ErrorRecord $_
710
+ }
711
+ finally {
712
+ $actionPipeline.Dispose()
713
+ if ($Script:AnsibleTempScripts) {
714
+ Remove-Item -LiteralPath $Script:AnsibleTempScripts -Force -ErrorAction Ignore
715
+ }
236
716
  }
237
- Write-AnsibleLog "INFO - ending exec_wrapper" "exec_wrapper"
238
717
  }