ansible-core 2.18.5rc1__py3-none-any.whl → 2.19.0b2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (710) hide show
  1. ansible/_internal/__init__.py +53 -0
  2. ansible/_internal/_ansiballz.py +265 -0
  3. ansible/_internal/_collection_proxy.py +47 -0
  4. ansible/_internal/_datatag/__init__.py +0 -0
  5. ansible/_internal/_datatag/_tags.py +130 -0
  6. ansible/_internal/_datatag/_utils.py +19 -0
  7. ansible/_internal/_datatag/_wrappers.py +33 -0
  8. ansible/_internal/_errors/__init__.py +0 -0
  9. ansible/_internal/_errors/_captured.py +128 -0
  10. ansible/_internal/_errors/_handler.py +91 -0
  11. ansible/_internal/_errors/_utils.py +310 -0
  12. ansible/_internal/_json/__init__.py +203 -0
  13. ansible/_internal/_json/_legacy_encoder.py +34 -0
  14. ansible/_internal/_json/_profiles/__init__.py +0 -0
  15. ansible/_internal/_json/_profiles/_cache_persistence.py +55 -0
  16. ansible/_internal/_json/_profiles/_inventory_legacy.py +40 -0
  17. ansible/_internal/_json/_profiles/_legacy.py +197 -0
  18. ansible/_internal/_locking.py +21 -0
  19. ansible/_internal/_plugins/__init__.py +0 -0
  20. ansible/_internal/_plugins/_cache.py +57 -0
  21. ansible/_internal/_task.py +78 -0
  22. ansible/_internal/_templating/__init__.py +10 -0
  23. ansible/_internal/_templating/_access.py +86 -0
  24. ansible/_internal/_templating/_chain_templar.py +63 -0
  25. ansible/_internal/_templating/_datatag.py +95 -0
  26. ansible/_internal/_templating/_engine.py +588 -0
  27. ansible/_internal/_templating/_errors.py +28 -0
  28. ansible/_internal/_templating/_jinja_bits.py +1066 -0
  29. ansible/_internal/_templating/_jinja_common.py +332 -0
  30. ansible/_internal/_templating/_jinja_patches.py +44 -0
  31. ansible/_internal/_templating/_jinja_plugins.py +345 -0
  32. ansible/_internal/_templating/_lazy_containers.py +633 -0
  33. ansible/_internal/_templating/_marker_behaviors.py +103 -0
  34. ansible/_internal/_templating/_transform.py +63 -0
  35. ansible/_internal/_templating/_utils.py +107 -0
  36. ansible/_internal/_wrapt.py +1052 -0
  37. ansible/_internal/_yaml/__init__.py +0 -0
  38. ansible/_internal/_yaml/_constructor.py +240 -0
  39. ansible/_internal/_yaml/_dumper.py +62 -0
  40. ansible/_internal/_yaml/_errors.py +166 -0
  41. ansible/_internal/_yaml/_loader.py +66 -0
  42. ansible/_internal/ansible_collections/ansible/_protomatter/README.md +11 -0
  43. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/action/debug.py +36 -0
  44. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/apply_trust.py +19 -0
  45. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/dump_object.py +18 -0
  46. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/finalize.py +16 -0
  47. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/origin.py +18 -0
  48. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/python_literal_eval.py +24 -0
  49. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/python_literal_eval.yml +33 -0
  50. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/tag_names.py +16 -0
  51. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/true_type.py +17 -0
  52. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/unmask.py +49 -0
  53. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/lookup/config.py +21 -0
  54. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/lookup/config.yml +2 -0
  55. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged.py +15 -0
  56. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged.yml +19 -0
  57. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged_with.py +18 -0
  58. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged_with.yml +19 -0
  59. ansible/cli/__init__.py +159 -89
  60. ansible/cli/_ssh_askpass.py +47 -0
  61. ansible/cli/adhoc.py +14 -7
  62. ansible/cli/arguments/option_helpers.py +154 -7
  63. ansible/cli/config.py +43 -68
  64. ansible/cli/console.py +10 -8
  65. ansible/cli/doc.py +62 -53
  66. ansible/cli/galaxy.py +27 -20
  67. ansible/cli/inventory.py +28 -26
  68. ansible/cli/playbook.py +4 -12
  69. ansible/cli/pull.py +51 -11
  70. ansible/cli/scripts/ansible_connection_cli_stub.py +7 -7
  71. ansible/cli/vault.py +12 -11
  72. ansible/compat/__init__.py +2 -2
  73. ansible/config/base.yml +166 -112
  74. ansible/config/manager.py +52 -49
  75. ansible/constants.py +3 -4
  76. ansible/errors/__init__.py +277 -235
  77. ansible/executor/interpreter_discovery.py +28 -149
  78. ansible/executor/module_common.py +426 -493
  79. ansible/executor/play_iterator.py +22 -27
  80. ansible/executor/playbook_executor.py +11 -11
  81. ansible/executor/powershell/async_watchdog.ps1 +97 -102
  82. ansible/executor/powershell/async_wrapper.ps1 +202 -151
  83. ansible/executor/powershell/become_wrapper.ps1 +89 -144
  84. ansible/executor/powershell/bootstrap_wrapper.ps1 +24 -9
  85. ansible/executor/powershell/coverage_wrapper.ps1 +82 -135
  86. ansible/executor/powershell/exec_wrapper.ps1 +462 -196
  87. ansible/executor/powershell/module_manifest.py +417 -265
  88. ansible/executor/powershell/module_wrapper.ps1 +169 -186
  89. ansible/executor/powershell/psrp_fetch_file.ps1 +41 -0
  90. ansible/executor/powershell/psrp_put_file.ps1 +122 -0
  91. ansible/executor/powershell/winrm_fetch_file.ps1 +46 -0
  92. ansible/executor/powershell/winrm_put_file.ps1 +36 -0
  93. ansible/executor/process/worker.py +161 -96
  94. ansible/executor/stats.py +5 -5
  95. ansible/executor/task_executor.py +268 -258
  96. ansible/executor/task_queue_manager.py +124 -90
  97. ansible/executor/task_result.py +183 -78
  98. ansible/galaxy/__init__.py +2 -2
  99. ansible/galaxy/api.py +22 -18
  100. ansible/galaxy/collection/__init__.py +1 -1
  101. ansible/galaxy/collection/concrete_artifact_manager.py +8 -11
  102. ansible/galaxy/dependency_resolution/dataclasses.py +14 -4
  103. ansible/galaxy/dependency_resolution/providers.py +1 -1
  104. ansible/galaxy/dependency_resolution/reporters.py +81 -0
  105. ansible/galaxy/role.py +4 -8
  106. ansible/galaxy/token.py +28 -21
  107. ansible/inventory/data.py +47 -57
  108. ansible/inventory/group.py +44 -72
  109. ansible/inventory/helpers.py +9 -0
  110. ansible/inventory/host.py +32 -54
  111. ansible/inventory/manager.py +78 -34
  112. ansible/keyword_desc.yml +1 -1
  113. ansible/module_utils/_internal/__init__.py +55 -0
  114. ansible/module_utils/_internal/_ambient_context.py +58 -0
  115. ansible/module_utils/_internal/_ansiballz.py +133 -0
  116. ansible/module_utils/_internal/_concurrent/_daemon_threading.py +1 -0
  117. ansible/module_utils/_internal/_dataclass_annotation_patch.py +64 -0
  118. ansible/module_utils/_internal/_dataclass_validation.py +217 -0
  119. ansible/module_utils/_internal/_datatag/__init__.py +928 -0
  120. ansible/module_utils/_internal/_datatag/_tags.py +38 -0
  121. ansible/module_utils/_internal/_debugging.py +31 -0
  122. ansible/module_utils/_internal/_errors.py +30 -0
  123. ansible/module_utils/_internal/_json/__init__.py +63 -0
  124. ansible/module_utils/_internal/_json/_legacy_encoder.py +26 -0
  125. ansible/module_utils/_internal/_json/_profiles/__init__.py +410 -0
  126. ansible/module_utils/_internal/_json/_profiles/_fallback_to_str.py +73 -0
  127. ansible/module_utils/_internal/_json/_profiles/_module_legacy_c2m.py +31 -0
  128. ansible/module_utils/_internal/_json/_profiles/_module_legacy_m2c.py +35 -0
  129. ansible/module_utils/_internal/_json/_profiles/_module_modern_c2m.py +35 -0
  130. ansible/module_utils/_internal/_json/_profiles/_module_modern_m2c.py +33 -0
  131. ansible/module_utils/_internal/_json/_profiles/_tagless.py +50 -0
  132. ansible/module_utils/_internal/_patches/__init__.py +66 -0
  133. ansible/module_utils/_internal/_patches/_dataclass_annotation_patch.py +55 -0
  134. ansible/module_utils/_internal/_patches/_socket_patch.py +34 -0
  135. ansible/module_utils/_internal/_patches/_sys_intern_patch.py +34 -0
  136. ansible/module_utils/_internal/_plugin_exec_context.py +49 -0
  137. ansible/module_utils/_internal/_testing.py +0 -0
  138. ansible/module_utils/_internal/_traceback.py +89 -0
  139. ansible/module_utils/ansible_release.py +2 -2
  140. ansible/module_utils/api.py +1 -2
  141. ansible/module_utils/basic.py +152 -120
  142. ansible/module_utils/common/_utils.py +24 -28
  143. ansible/module_utils/common/collections.py +1 -2
  144. ansible/module_utils/common/dict_transformations.py +2 -2
  145. ansible/module_utils/common/file.py +2 -2
  146. ansible/module_utils/common/json.py +90 -84
  147. ansible/module_utils/common/locale.py +2 -2
  148. ansible/module_utils/common/messages.py +108 -0
  149. ansible/module_utils/common/parameters.py +27 -24
  150. ansible/module_utils/common/process.py +2 -2
  151. ansible/module_utils/common/respawn.py +41 -19
  152. ansible/module_utils/common/sentinel.py +66 -0
  153. ansible/module_utils/common/sys_info.py +8 -8
  154. ansible/module_utils/common/text/converters.py +16 -37
  155. ansible/module_utils/common/validation.py +35 -24
  156. ansible/module_utils/common/warnings.py +86 -25
  157. ansible/module_utils/common/yaml.py +29 -3
  158. ansible/module_utils/compat/datetime.py +33 -21
  159. ansible/module_utils/compat/paramiko.py +21 -10
  160. ansible/module_utils/compat/typing.py +6 -5
  161. ansible/module_utils/connection.py +2 -2
  162. ansible/module_utils/csharp/Ansible.Basic.cs +14 -11
  163. ansible/module_utils/csharp/Ansible.Become.cs +1 -0
  164. ansible/module_utils/csharp/Ansible._Async.cs +517 -0
  165. ansible/module_utils/datatag.py +46 -0
  166. ansible/module_utils/distro/__init__.py +2 -2
  167. ansible/module_utils/facts/ansible_collector.py +4 -5
  168. ansible/module_utils/facts/collector.py +13 -14
  169. ansible/module_utils/facts/compat.py +4 -4
  170. ansible/module_utils/facts/default_collectors.py +1 -1
  171. ansible/module_utils/facts/hardware/aix.py +34 -0
  172. ansible/module_utils/facts/hardware/base.py +1 -1
  173. ansible/module_utils/facts/hardware/darwin.py +1 -3
  174. ansible/module_utils/facts/hardware/freebsd.py +2 -2
  175. ansible/module_utils/facts/hardware/linux.py +4 -4
  176. ansible/module_utils/facts/namespace.py +1 -1
  177. ansible/module_utils/facts/network/base.py +1 -1
  178. ansible/module_utils/facts/network/fc_wwn.py +1 -2
  179. ansible/module_utils/facts/network/iscsi.py +1 -2
  180. ansible/module_utils/facts/network/nvme.py +1 -2
  181. ansible/module_utils/facts/other/facter.py +1 -2
  182. ansible/module_utils/facts/other/ohai.py +2 -3
  183. ansible/module_utils/facts/system/apparmor.py +1 -2
  184. ansible/module_utils/facts/system/caps.py +1 -1
  185. ansible/module_utils/facts/system/chroot.py +1 -2
  186. ansible/module_utils/facts/system/cmdline.py +1 -2
  187. ansible/module_utils/facts/system/date_time.py +5 -3
  188. ansible/module_utils/facts/system/distribution.py +9 -8
  189. ansible/module_utils/facts/system/dns.py +1 -1
  190. ansible/module_utils/facts/system/env.py +1 -2
  191. ansible/module_utils/facts/system/fips.py +7 -20
  192. ansible/module_utils/facts/system/loadavg.py +1 -2
  193. ansible/module_utils/facts/system/local.py +1 -2
  194. ansible/module_utils/facts/system/lsb.py +1 -2
  195. ansible/module_utils/facts/system/pkg_mgr.py +1 -2
  196. ansible/module_utils/facts/system/platform.py +1 -2
  197. ansible/module_utils/facts/system/python.py +1 -2
  198. ansible/module_utils/facts/system/selinux.py +1 -1
  199. ansible/module_utils/facts/system/service_mgr.py +1 -2
  200. ansible/module_utils/facts/system/ssh_pub_keys.py +1 -1
  201. ansible/module_utils/facts/system/systemd.py +1 -1
  202. ansible/module_utils/facts/system/user.py +1 -2
  203. ansible/module_utils/facts/utils.py +3 -3
  204. ansible/module_utils/facts/virtual/base.py +1 -1
  205. ansible/module_utils/facts/virtual/sunos.py +3 -15
  206. ansible/module_utils/facts/virtual/sysctl.py +3 -16
  207. ansible/module_utils/json_utils.py +2 -2
  208. ansible/module_utils/parsing/convert_bool.py +1 -1
  209. ansible/module_utils/service.py +18 -21
  210. ansible/module_utils/splitter.py +7 -7
  211. ansible/module_utils/testing.py +31 -0
  212. ansible/module_utils/urls.py +60 -31
  213. ansible/modules/add_host.py +4 -4
  214. ansible/modules/apt.py +60 -46
  215. ansible/modules/apt_key.py +19 -12
  216. ansible/modules/apt_repository.py +19 -16
  217. ansible/modules/assemble.py +6 -6
  218. ansible/modules/assert.py +4 -4
  219. ansible/modules/async_status.py +10 -12
  220. ansible/modules/async_wrapper.py +8 -3
  221. ansible/modules/blockinfile.py +6 -7
  222. ansible/modules/command.py +10 -17
  223. ansible/modules/copy.py +57 -144
  224. ansible/modules/cron.py +20 -15
  225. ansible/modules/deb822_repository.py +8 -9
  226. ansible/modules/debconf.py +5 -5
  227. ansible/modules/debug.py +4 -4
  228. ansible/modules/dnf.py +8 -8
  229. ansible/modules/dnf5.py +39 -13
  230. ansible/modules/dpkg_selections.py +4 -4
  231. ansible/modules/expect.py +8 -10
  232. ansible/modules/fail.py +4 -4
  233. ansible/modules/fetch.py +4 -4
  234. ansible/modules/file.py +174 -133
  235. ansible/modules/find.py +19 -17
  236. ansible/modules/gather_facts.py +3 -3
  237. ansible/modules/get_url.py +59 -53
  238. ansible/modules/getent.py +7 -9
  239. ansible/modules/git.py +28 -25
  240. ansible/modules/group.py +6 -6
  241. ansible/modules/group_by.py +4 -4
  242. ansible/modules/hostname.py +13 -29
  243. ansible/modules/import_playbook.py +6 -6
  244. ansible/modules/import_role.py +6 -6
  245. ansible/modules/import_tasks.py +6 -6
  246. ansible/modules/include_role.py +6 -6
  247. ansible/modules/include_tasks.py +6 -6
  248. ansible/modules/include_vars.py +6 -6
  249. ansible/modules/iptables.py +86 -73
  250. ansible/modules/known_hosts.py +10 -10
  251. ansible/modules/lineinfile.py +5 -5
  252. ansible/modules/meta.py +4 -4
  253. ansible/modules/mount_facts.py +2 -2
  254. ansible/modules/package.py +4 -4
  255. ansible/modules/package_facts.py +22 -10
  256. ansible/modules/pause.py +6 -6
  257. ansible/modules/ping.py +6 -6
  258. ansible/modules/pip.py +10 -11
  259. ansible/modules/raw.py +4 -4
  260. ansible/modules/reboot.py +6 -6
  261. ansible/modules/replace.py +9 -13
  262. ansible/modules/rpm_key.py +7 -8
  263. ansible/modules/script.py +4 -4
  264. ansible/modules/service.py +7 -8
  265. ansible/modules/service_facts.py +87 -10
  266. ansible/modules/set_fact.py +5 -5
  267. ansible/modules/set_stats.py +4 -4
  268. ansible/modules/setup.py +2 -2
  269. ansible/modules/shell.py +6 -6
  270. ansible/modules/slurp.py +6 -6
  271. ansible/modules/stat.py +9 -23
  272. ansible/modules/subversion.py +15 -15
  273. ansible/modules/systemd.py +6 -6
  274. ansible/modules/systemd_service.py +6 -6
  275. ansible/modules/sysvinit.py +6 -6
  276. ansible/modules/tempfile.py +5 -6
  277. ansible/modules/template.py +6 -6
  278. ansible/modules/unarchive.py +32 -11
  279. ansible/modules/uri.py +33 -26
  280. ansible/modules/user.py +53 -34
  281. ansible/modules/validate_argument_spec.py +10 -7
  282. ansible/modules/wait_for.py +32 -27
  283. ansible/modules/wait_for_connection.py +6 -6
  284. ansible/modules/yum_repository.py +6 -6
  285. ansible/parsing/ajson.py +14 -32
  286. ansible/parsing/dataloader.py +99 -54
  287. ansible/parsing/mod_args.py +28 -44
  288. ansible/parsing/plugin_docs.py +21 -86
  289. ansible/parsing/quoting.py +1 -1
  290. ansible/parsing/splitter.py +27 -12
  291. ansible/parsing/utils/addresses.py +24 -24
  292. ansible/parsing/utils/jsonify.py +5 -1
  293. ansible/parsing/utils/yaml.py +32 -61
  294. ansible/parsing/vault/__init__.py +319 -87
  295. ansible/parsing/yaml/__init__.py +0 -18
  296. ansible/parsing/yaml/dumper.py +6 -120
  297. ansible/parsing/yaml/loader.py +6 -39
  298. ansible/parsing/yaml/objects.py +43 -335
  299. ansible/playbook/__init__.py +1 -1
  300. ansible/playbook/attribute.py +8 -3
  301. ansible/playbook/base.py +182 -132
  302. ansible/playbook/block.py +26 -24
  303. ansible/playbook/collectionsearch.py +1 -15
  304. ansible/playbook/conditional.py +3 -77
  305. ansible/playbook/handler.py +8 -2
  306. ansible/playbook/helpers.py +41 -53
  307. ansible/playbook/included_file.py +31 -27
  308. ansible/playbook/loop_control.py +2 -2
  309. ansible/playbook/play.py +85 -44
  310. ansible/playbook/play_context.py +12 -17
  311. ansible/playbook/playbook_include.py +14 -15
  312. ansible/playbook/role/__init__.py +24 -26
  313. ansible/playbook/role/definition.py +15 -17
  314. ansible/playbook/role/include.py +2 -4
  315. ansible/playbook/role/metadata.py +10 -11
  316. ansible/playbook/role_include.py +3 -3
  317. ansible/playbook/taggable.py +13 -8
  318. ansible/playbook/task.py +188 -118
  319. ansible/playbook/task_include.py +5 -5
  320. ansible/plugins/__init__.py +68 -21
  321. ansible/plugins/action/__init__.py +209 -176
  322. ansible/plugins/action/add_host.py +1 -1
  323. ansible/plugins/action/assemble.py +1 -1
  324. ansible/plugins/action/assert.py +54 -66
  325. ansible/plugins/action/copy.py +7 -11
  326. ansible/plugins/action/debug.py +37 -31
  327. ansible/plugins/action/dnf.py +3 -4
  328. ansible/plugins/action/fail.py +1 -1
  329. ansible/plugins/action/fetch.py +4 -5
  330. ansible/plugins/action/gather_facts.py +7 -6
  331. ansible/plugins/action/group_by.py +1 -1
  332. ansible/plugins/action/include_vars.py +10 -11
  333. ansible/plugins/action/package.py +3 -6
  334. ansible/plugins/action/pause.py +2 -2
  335. ansible/plugins/action/script.py +15 -8
  336. ansible/plugins/action/service.py +6 -11
  337. ansible/plugins/action/set_fact.py +3 -12
  338. ansible/plugins/action/set_stats.py +3 -8
  339. ansible/plugins/action/template.py +35 -59
  340. ansible/plugins/action/unarchive.py +1 -1
  341. ansible/plugins/action/validate_argument_spec.py +5 -5
  342. ansible/plugins/action/wait_for_connection.py +1 -1
  343. ansible/plugins/become/__init__.py +31 -8
  344. ansible/plugins/become/runas.py +71 -0
  345. ansible/plugins/become/su.py +13 -8
  346. ansible/plugins/become/sudo.py +19 -0
  347. ansible/plugins/cache/__init__.py +35 -44
  348. ansible/plugins/cache/base.py +8 -0
  349. ansible/plugins/cache/jsonfile.py +10 -16
  350. ansible/plugins/cache/memory.py +6 -12
  351. ansible/plugins/callback/__init__.py +284 -179
  352. ansible/plugins/callback/default.py +99 -92
  353. ansible/plugins/callback/junit.py +44 -39
  354. ansible/plugins/callback/minimal.py +28 -25
  355. ansible/plugins/callback/oneline.py +28 -21
  356. ansible/plugins/callback/tree.py +16 -11
  357. ansible/plugins/connection/__init__.py +47 -34
  358. ansible/plugins/connection/local.py +150 -54
  359. ansible/plugins/connection/paramiko_ssh.py +21 -18
  360. ansible/plugins/connection/psrp.py +76 -165
  361. ansible/plugins/connection/ssh.py +301 -78
  362. ansible/plugins/connection/winrm.py +58 -140
  363. ansible/plugins/doc_fragments/action_common_attributes.py +14 -14
  364. ansible/plugins/doc_fragments/action_core.py +6 -6
  365. ansible/plugins/doc_fragments/backup.py +2 -2
  366. ansible/plugins/doc_fragments/checksum_common.py +27 -0
  367. ansible/plugins/doc_fragments/constructed.py +6 -2
  368. ansible/plugins/doc_fragments/decrypt.py +2 -2
  369. ansible/plugins/doc_fragments/default_callback.py +2 -2
  370. ansible/plugins/doc_fragments/files.py +2 -2
  371. ansible/plugins/doc_fragments/inventory_cache.py +2 -2
  372. ansible/plugins/doc_fragments/result_format_callback.py +2 -2
  373. ansible/plugins/doc_fragments/return_common.py +2 -2
  374. ansible/plugins/doc_fragments/template_common.py +4 -4
  375. ansible/plugins/doc_fragments/url.py +17 -1
  376. ansible/plugins/doc_fragments/url_windows.py +2 -2
  377. ansible/plugins/doc_fragments/validate.py +2 -2
  378. ansible/plugins/doc_fragments/vars_plugin_staging.py +2 -2
  379. ansible/plugins/filter/__init__.py +6 -2
  380. ansible/plugins/filter/b64decode.yml +22 -0
  381. ansible/plugins/filter/b64encode.yml +22 -0
  382. ansible/plugins/filter/bool.yml +11 -4
  383. ansible/plugins/filter/core.py +225 -108
  384. ansible/plugins/filter/encryption.py +32 -32
  385. ansible/plugins/filter/flatten.yml +3 -2
  386. ansible/plugins/filter/human_to_bytes.yml +1 -1
  387. ansible/plugins/filter/mathstuff.py +30 -37
  388. ansible/plugins/filter/password_hash.yml +8 -0
  389. ansible/plugins/filter/regex_search.yml +1 -4
  390. ansible/plugins/filter/split.yml +1 -1
  391. ansible/plugins/filter/to_nice_yaml.yml +0 -4
  392. ansible/plugins/filter/to_yaml.yml +0 -4
  393. ansible/plugins/filter/unvault.yml +1 -1
  394. ansible/plugins/filter/urls.py +1 -1
  395. ansible/plugins/filter/urlsplit.py +8 -9
  396. ansible/plugins/filter/vault.yml +14 -9
  397. ansible/plugins/filter/win_basename.yml +6 -1
  398. ansible/plugins/filter/win_dirname.yml +5 -0
  399. ansible/plugins/inventory/__init__.py +97 -77
  400. ansible/plugins/inventory/advanced_host_list.py +7 -5
  401. ansible/plugins/inventory/auto.py +11 -4
  402. ansible/plugins/inventory/constructed.py +21 -24
  403. ansible/plugins/inventory/generator.py +16 -11
  404. ansible/plugins/inventory/host_list.py +7 -5
  405. ansible/plugins/inventory/ini.py +78 -44
  406. ansible/plugins/inventory/script.py +189 -119
  407. ansible/plugins/inventory/toml.py +16 -126
  408. ansible/plugins/inventory/yaml.py +10 -8
  409. ansible/plugins/list.py +3 -3
  410. ansible/plugins/loader.py +197 -82
  411. ansible/plugins/lookup/__init__.py +21 -4
  412. ansible/plugins/lookup/config.py +21 -35
  413. ansible/plugins/lookup/csvfile.py +3 -2
  414. ansible/plugins/lookup/dict.py +1 -6
  415. ansible/plugins/lookup/env.py +12 -9
  416. ansible/plugins/lookup/file.py +5 -8
  417. ansible/plugins/lookup/first_found.py +86 -55
  418. ansible/plugins/lookup/indexed_items.py +1 -10
  419. ansible/plugins/lookup/ini.py +14 -13
  420. ansible/plugins/lookup/items.py +1 -1
  421. ansible/plugins/lookup/lines.py +8 -1
  422. ansible/plugins/lookup/list.py +1 -1
  423. ansible/plugins/lookup/nested.py +2 -18
  424. ansible/plugins/lookup/password.py +5 -5
  425. ansible/plugins/lookup/pipe.py +5 -7
  426. ansible/plugins/lookup/sequence.py +18 -8
  427. ansible/plugins/lookup/subelements.py +1 -4
  428. ansible/plugins/lookup/template.py +42 -36
  429. ansible/plugins/lookup/together.py +0 -12
  430. ansible/plugins/lookup/unvault.py +1 -5
  431. ansible/plugins/lookup/url.py +2 -8
  432. ansible/plugins/lookup/vars.py +16 -24
  433. ansible/plugins/shell/__init__.py +2 -2
  434. ansible/plugins/shell/cmd.py +2 -2
  435. ansible/plugins/shell/powershell.py +39 -22
  436. ansible/plugins/shell/sh.py +3 -2
  437. ansible/plugins/strategy/__init__.py +159 -184
  438. ansible/plugins/strategy/debug.py +2 -2
  439. ansible/plugins/strategy/free.py +16 -31
  440. ansible/plugins/strategy/host_pinned.py +2 -2
  441. ansible/plugins/strategy/linear.py +41 -41
  442. ansible/plugins/terminal/__init__.py +4 -4
  443. ansible/plugins/test/__init__.py +7 -2
  444. ansible/plugins/test/core.py +55 -21
  445. ansible/plugins/test/files.py +1 -1
  446. ansible/plugins/test/mathstuff.py +3 -3
  447. ansible/plugins/test/uri.py +3 -3
  448. ansible/plugins/vars/host_group_vars.py +7 -14
  449. ansible/release.py +2 -2
  450. ansible/template/__init__.py +370 -944
  451. ansible/utils/__init__.py +0 -18
  452. ansible/utils/_ssh_agent.py +657 -0
  453. ansible/utils/collection_loader/__init__.py +52 -5
  454. ansible/utils/collection_loader/_collection_config.py +5 -6
  455. ansible/utils/collection_loader/_collection_finder.py +79 -93
  456. ansible/utils/collection_loader/_collection_meta.py +13 -8
  457. ansible/utils/display.py +433 -63
  458. ansible/utils/encrypt.py +27 -19
  459. ansible/utils/fqcn.py +2 -2
  460. ansible/utils/hashing.py +2 -2
  461. ansible/utils/helpers.py +2 -2
  462. ansible/utils/listify.py +8 -8
  463. ansible/utils/lock.py +2 -2
  464. ansible/utils/path.py +4 -4
  465. ansible/utils/plugin_docs.py +14 -13
  466. ansible/utils/sentinel.py +4 -62
  467. ansible/utils/singleton.py +2 -0
  468. ansible/utils/ssh_functions.py +1 -1
  469. ansible/utils/unsafe_proxy.py +23 -332
  470. ansible/utils/vars.py +51 -8
  471. ansible/utils/version.py +2 -2
  472. ansible/vars/clean.py +5 -5
  473. ansible/vars/hostvars.py +60 -90
  474. ansible/vars/manager.py +206 -282
  475. ansible/vars/reserved.py +8 -9
  476. ansible_core-2.19.0b2.dist-info/BSD-3-Clause.txt +28 -0
  477. {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/METADATA +5 -4
  478. ansible_core-2.19.0b2.dist-info/RECORD +1072 -0
  479. {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/WHEEL +1 -1
  480. ansible_test/_data/completion/docker.txt +7 -7
  481. ansible_test/_data/completion/remote.txt +6 -6
  482. ansible_test/_data/completion/windows.txt +1 -0
  483. ansible_test/_data/requirements/ansible.txt +2 -2
  484. ansible_test/_data/requirements/sanity.ansible-doc.txt +3 -3
  485. ansible_test/_data/requirements/sanity.changelog.txt +1 -1
  486. ansible_test/_data/requirements/sanity.import.plugin.txt +2 -2
  487. ansible_test/_data/requirements/sanity.pylint.txt +4 -4
  488. ansible_test/_data/requirements/sanity.validate-modules.txt +2 -2
  489. ansible_test/_data/requirements/sanity.yamllint.txt +1 -1
  490. ansible_test/_data/requirements/units.txt +1 -0
  491. ansible_test/_internal/__init__.py +1 -0
  492. ansible_test/_internal/ansible_util.py +2 -0
  493. ansible_test/_internal/become.py +1 -0
  494. ansible_test/_internal/bootstrap.py +1 -0
  495. ansible_test/_internal/cache.py +1 -0
  496. ansible_test/_internal/cgroup.py +1 -0
  497. ansible_test/_internal/ci/__init__.py +1 -0
  498. ansible_test/_internal/ci/azp.py +1 -0
  499. ansible_test/_internal/ci/local.py +1 -0
  500. ansible_test/_internal/classification/__init__.py +1 -0
  501. ansible_test/_internal/classification/common.py +1 -0
  502. ansible_test/_internal/classification/csharp.py +1 -0
  503. ansible_test/_internal/classification/powershell.py +1 -0
  504. ansible_test/_internal/classification/python.py +1 -0
  505. ansible_test/_internal/cli/__init__.py +1 -0
  506. ansible_test/_internal/cli/actions.py +1 -0
  507. ansible_test/_internal/cli/argparsing/__init__.py +1 -0
  508. ansible_test/_internal/cli/argparsing/actions.py +1 -0
  509. ansible_test/_internal/cli/argparsing/argcompletion.py +1 -0
  510. ansible_test/_internal/cli/argparsing/parsers.py +1 -0
  511. ansible_test/_internal/cli/commands/__init__.py +11 -0
  512. ansible_test/_internal/cli/commands/coverage/__init__.py +1 -0
  513. ansible_test/_internal/cli/commands/coverage/analyze/__init__.py +1 -0
  514. ansible_test/_internal/cli/commands/coverage/analyze/targets/__init__.py +1 -0
  515. ansible_test/_internal/cli/commands/coverage/analyze/targets/combine.py +1 -0
  516. ansible_test/_internal/cli/commands/coverage/analyze/targets/expand.py +1 -0
  517. ansible_test/_internal/cli/commands/coverage/analyze/targets/filter.py +1 -0
  518. ansible_test/_internal/cli/commands/coverage/analyze/targets/generate.py +1 -0
  519. ansible_test/_internal/cli/commands/coverage/analyze/targets/missing.py +1 -0
  520. ansible_test/_internal/cli/commands/coverage/combine.py +1 -0
  521. ansible_test/_internal/cli/commands/coverage/erase.py +1 -0
  522. ansible_test/_internal/cli/commands/coverage/html.py +1 -0
  523. ansible_test/_internal/cli/commands/coverage/report.py +1 -0
  524. ansible_test/_internal/cli/commands/coverage/xml.py +1 -0
  525. ansible_test/_internal/cli/commands/env.py +1 -0
  526. ansible_test/_internal/cli/commands/integration/__init__.py +1 -0
  527. ansible_test/_internal/cli/commands/integration/network.py +1 -0
  528. ansible_test/_internal/cli/commands/integration/posix.py +1 -0
  529. ansible_test/_internal/cli/commands/integration/windows.py +1 -0
  530. ansible_test/_internal/cli/commands/sanity.py +9 -0
  531. ansible_test/_internal/cli/commands/shell.py +1 -0
  532. ansible_test/_internal/cli/commands/units.py +1 -0
  533. ansible_test/_internal/cli/compat.py +1 -0
  534. ansible_test/_internal/cli/completers.py +1 -0
  535. ansible_test/_internal/cli/converters.py +1 -0
  536. ansible_test/_internal/cli/environments.py +1 -0
  537. ansible_test/_internal/cli/epilog.py +1 -0
  538. ansible_test/_internal/cli/parsers/__init__.py +1 -0
  539. ansible_test/_internal/cli/parsers/base_argument_parsers.py +1 -0
  540. ansible_test/_internal/cli/parsers/helpers.py +1 -0
  541. ansible_test/_internal/cli/parsers/host_config_parsers.py +1 -0
  542. ansible_test/_internal/cli/parsers/key_value_parsers.py +1 -0
  543. ansible_test/_internal/cli/parsers/value_parsers.py +1 -0
  544. ansible_test/_internal/commands/__init__.py +1 -0
  545. ansible_test/_internal/commands/coverage/__init__.py +2 -1
  546. ansible_test/_internal/commands/coverage/analyze/__init__.py +1 -0
  547. ansible_test/_internal/commands/coverage/analyze/targets/__init__.py +1 -0
  548. ansible_test/_internal/commands/coverage/analyze/targets/combine.py +1 -0
  549. ansible_test/_internal/commands/coverage/analyze/targets/expand.py +1 -0
  550. ansible_test/_internal/commands/coverage/analyze/targets/filter.py +1 -0
  551. ansible_test/_internal/commands/coverage/analyze/targets/generate.py +1 -0
  552. ansible_test/_internal/commands/coverage/analyze/targets/missing.py +1 -0
  553. ansible_test/_internal/commands/coverage/combine.py +2 -1
  554. ansible_test/_internal/commands/coverage/erase.py +1 -0
  555. ansible_test/_internal/commands/coverage/html.py +1 -0
  556. ansible_test/_internal/commands/coverage/report.py +1 -0
  557. ansible_test/_internal/commands/coverage/xml.py +1 -0
  558. ansible_test/_internal/commands/env/__init__.py +2 -0
  559. ansible_test/_internal/commands/integration/__init__.py +4 -0
  560. ansible_test/_internal/commands/integration/cloud/__init__.py +1 -0
  561. ansible_test/_internal/commands/integration/cloud/acme.py +2 -1
  562. ansible_test/_internal/commands/integration/cloud/aws.py +1 -0
  563. ansible_test/_internal/commands/integration/cloud/azure.py +1 -0
  564. ansible_test/_internal/commands/integration/cloud/cs.py +1 -0
  565. ansible_test/_internal/commands/integration/cloud/digitalocean.py +1 -0
  566. ansible_test/_internal/commands/integration/cloud/galaxy.py +3 -2
  567. ansible_test/_internal/commands/integration/cloud/hcloud.py +1 -0
  568. ansible_test/_internal/commands/integration/cloud/httptester.py +2 -1
  569. ansible_test/_internal/commands/integration/cloud/nios.py +2 -1
  570. ansible_test/_internal/commands/integration/cloud/opennebula.py +1 -0
  571. ansible_test/_internal/commands/integration/cloud/openshift.py +1 -0
  572. ansible_test/_internal/commands/integration/cloud/scaleway.py +1 -0
  573. ansible_test/_internal/commands/integration/cloud/vcenter.py +1 -0
  574. ansible_test/_internal/commands/integration/cloud/vultr.py +1 -0
  575. ansible_test/_internal/commands/integration/coverage.py +1 -0
  576. ansible_test/_internal/commands/integration/filters.py +1 -0
  577. ansible_test/_internal/commands/integration/network.py +1 -0
  578. ansible_test/_internal/commands/integration/posix.py +1 -0
  579. ansible_test/_internal/commands/integration/windows.py +1 -0
  580. ansible_test/_internal/commands/sanity/__init__.py +16 -1
  581. ansible_test/_internal/commands/sanity/ansible_doc.py +1 -0
  582. ansible_test/_internal/commands/sanity/bin_symlinks.py +1 -0
  583. ansible_test/_internal/commands/sanity/compile.py +1 -0
  584. ansible_test/_internal/commands/sanity/ignores.py +1 -0
  585. ansible_test/_internal/commands/sanity/import.py +1 -0
  586. ansible_test/_internal/commands/sanity/integration_aliases.py +1 -0
  587. ansible_test/_internal/commands/sanity/pep8.py +1 -0
  588. ansible_test/_internal/commands/sanity/pslint.py +1 -0
  589. ansible_test/_internal/commands/sanity/pylint.py +24 -26
  590. ansible_test/_internal/commands/sanity/shellcheck.py +1 -0
  591. ansible_test/_internal/commands/sanity/validate_modules.py +1 -0
  592. ansible_test/_internal/commands/sanity/yamllint.py +1 -0
  593. ansible_test/_internal/commands/shell/__init__.py +1 -0
  594. ansible_test/_internal/commands/units/__init__.py +1 -0
  595. ansible_test/_internal/compat/__init__.py +1 -0
  596. ansible_test/_internal/compat/packaging.py +1 -0
  597. ansible_test/_internal/compat/yaml.py +1 -0
  598. ansible_test/_internal/completion.py +1 -0
  599. ansible_test/_internal/config.py +2 -0
  600. ansible_test/_internal/connections.py +1 -0
  601. ansible_test/_internal/constants.py +1 -0
  602. ansible_test/_internal/containers.py +1 -0
  603. ansible_test/_internal/content_config.py +1 -0
  604. ansible_test/_internal/core_ci.py +1 -0
  605. ansible_test/_internal/coverage_util.py +11 -10
  606. ansible_test/_internal/data.py +1 -0
  607. ansible_test/_internal/delegation.py +1 -0
  608. ansible_test/_internal/dev/__init__.py +1 -0
  609. ansible_test/_internal/dev/container_probe.py +1 -0
  610. ansible_test/_internal/diff.py +3 -2
  611. ansible_test/_internal/docker_util.py +2 -1
  612. ansible_test/_internal/encoding.py +1 -0
  613. ansible_test/_internal/executor.py +1 -0
  614. ansible_test/_internal/git.py +1 -0
  615. ansible_test/_internal/host_configs.py +1 -0
  616. ansible_test/_internal/host_profiles.py +1 -0
  617. ansible_test/_internal/http.py +1 -0
  618. ansible_test/_internal/init.py +1 -0
  619. ansible_test/_internal/inventory.py +35 -3
  620. ansible_test/_internal/io.py +1 -0
  621. ansible_test/_internal/metadata.py +1 -0
  622. ansible_test/_internal/payload.py +1 -0
  623. ansible_test/_internal/provider/__init__.py +1 -0
  624. ansible_test/_internal/provider/layout/__init__.py +1 -0
  625. ansible_test/_internal/provider/layout/ansible.py +1 -0
  626. ansible_test/_internal/provider/layout/collection.py +1 -0
  627. ansible_test/_internal/provider/layout/unsupported.py +1 -0
  628. ansible_test/_internal/provider/source/__init__.py +1 -0
  629. ansible_test/_internal/provider/source/git.py +1 -0
  630. ansible_test/_internal/provider/source/installed.py +1 -0
  631. ansible_test/_internal/provider/source/unsupported.py +1 -0
  632. ansible_test/_internal/provider/source/unversioned.py +1 -0
  633. ansible_test/_internal/provisioning.py +1 -0
  634. ansible_test/_internal/pypi_proxy.py +6 -5
  635. ansible_test/_internal/python_requirements.py +1 -0
  636. ansible_test/_internal/ssh.py +1 -0
  637. ansible_test/_internal/target.py +1 -0
  638. ansible_test/_internal/test.py +3 -2
  639. ansible_test/_internal/thread.py +1 -0
  640. ansible_test/_internal/timeout.py +1 -0
  641. ansible_test/_internal/util.py +1 -0
  642. ansible_test/_internal/util_common.py +5 -2
  643. ansible_test/_internal/venv.py +1 -0
  644. ansible_test/_util/controller/sanity/code-smell/action-plugin-docs.py +1 -0
  645. ansible_test/_util/controller/sanity/code-smell/changelog/sphinx.py +1 -0
  646. ansible_test/_util/controller/sanity/code-smell/changelog.py +1 -0
  647. ansible_test/_util/controller/sanity/code-smell/empty-init.py +1 -0
  648. ansible_test/_util/controller/sanity/code-smell/line-endings.py +1 -0
  649. ansible_test/_util/controller/sanity/code-smell/no-assert.py +1 -0
  650. ansible_test/_util/controller/sanity/code-smell/no-get-exception.py +1 -0
  651. ansible_test/_util/controller/sanity/code-smell/no-illegal-filenames.py +1 -0
  652. ansible_test/_util/controller/sanity/code-smell/no-smart-quotes.py +1 -0
  653. ansible_test/_util/controller/sanity/code-smell/replace-urlopen.py +1 -0
  654. ansible_test/_util/controller/sanity/code-smell/runtime-metadata.py +28 -1
  655. ansible_test/_util/controller/sanity/code-smell/shebang.py +1 -0
  656. ansible_test/_util/controller/sanity/code-smell/symlinks.py +1 -0
  657. ansible_test/_util/controller/sanity/code-smell/use-argspec-type-path.py +1 -0
  658. ansible_test/_util/controller/sanity/code-smell/use-compat-six.py +1 -0
  659. ansible_test/_util/controller/sanity/integration-aliases/yaml_to_json.py +2 -1
  660. ansible_test/_util/controller/sanity/pep8/current-ignore.txt +4 -0
  661. ansible_test/_util/controller/sanity/pylint/config/ansible-test-target.cfg +7 -5
  662. ansible_test/_util/controller/sanity/pylint/config/ansible-test.cfg +7 -5
  663. ansible_test/_util/controller/sanity/pylint/config/code-smell.cfg +7 -5
  664. ansible_test/_util/controller/sanity/pylint/config/collection.cfg +3 -5
  665. ansible_test/_util/controller/sanity/pylint/config/default.cfg +7 -7
  666. ansible_test/_util/controller/sanity/pylint/plugins/deprecated.py +1 -13
  667. ansible_test/_util/controller/sanity/pylint/plugins/hide_unraisable.py +1 -0
  668. ansible_test/_util/controller/sanity/pylint/plugins/string_format.py +1 -8
  669. ansible_test/_util/controller/sanity/pylint/plugins/unwanted.py +1 -8
  670. ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py +55 -28
  671. ansible_test/_util/controller/sanity/validate-modules/validate_modules/module_args.py +12 -5
  672. ansible_test/_util/controller/sanity/validate-modules/validate_modules/schema.py +13 -2
  673. ansible_test/_util/controller/sanity/validate-modules/validate_modules/utils.py +1 -0
  674. ansible_test/_util/controller/sanity/yamllint/yamllinter.py +35 -17
  675. ansible_test/_util/controller/tools/collection_detail.py +1 -0
  676. ansible_test/_util/controller/tools/yaml_to_json.py +2 -1
  677. ansible_test/_util/target/pytest/plugins/ansible_forked.py +6 -1
  678. ansible_test/_util/target/pytest/plugins/ansible_pytest_collections.py +2 -1
  679. ansible_test/_util/target/pytest/plugins/ansible_pytest_coverage.py +1 -0
  680. ansible_test/_util/target/sanity/compile/compile.py +1 -0
  681. ansible_test/_util/target/sanity/import/importer.py +15 -16
  682. ansible_test/_util/target/setup/bootstrap.sh +9 -20
  683. ansible_test/_util/target/setup/probe_cgroups.py +1 -0
  684. ansible_test/_util/target/setup/quiet_pip.py +1 -0
  685. ansible_test/_util/target/setup/requirements.py +35 -27
  686. ansible_test/_util/target/tools/virtualenvcheck.py +2 -1
  687. ansible_test/_util/target/tools/yamlcheck.py +2 -1
  688. ansible/compat/selectors.py +0 -32
  689. ansible/errors/yaml_strings.py +0 -138
  690. ansible/executor/action_write_locks.py +0 -44
  691. ansible/executor/discovery/python_target.py +0 -47
  692. ansible/executor/powershell/module_powershell_wrapper.ps1 +0 -86
  693. ansible/executor/powershell/module_script_wrapper.ps1 +0 -22
  694. ansible/module_utils/compat/importlib.py +0 -26
  695. ansible/module_utils/compat/selectors.py +0 -32
  696. ansible/module_utils/pycompat24.py +0 -73
  697. ansible/parsing/yaml/constructor.py +0 -178
  698. ansible/template/native_helpers.py +0 -251
  699. ansible/template/template.py +0 -43
  700. ansible/template/vars.py +0 -77
  701. ansible/utils/native_jinja.py +0 -11
  702. ansible/vars/fact_cache.py +0 -71
  703. ansible_core-2.18.5rc1.dist-info/RECORD +0 -992
  704. {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/Apache-License.txt +0 -0
  705. {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/COPYING +0 -0
  706. {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/MIT-license.txt +0 -0
  707. {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/PSF-license.txt +0 -0
  708. {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/entry_points.txt +0 -0
  709. {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/simplified_bsd.txt +0 -0
  710. {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/top_level.txt +0 -0
@@ -20,7 +20,7 @@ import os
20
20
 
21
21
 
22
22
  def get_file_content(path, default=None, strip=True):
23
- '''
23
+ """
24
24
  Return the contents of a given file path
25
25
 
26
26
  :args path: path to file to return contents from
@@ -28,7 +28,7 @@ def get_file_content(path, default=None, strip=True):
28
28
  :args strip: controls if we strip whitespace from the result or not
29
29
 
30
30
  :returns: String with file contents (optionally stripped) or 'default' value
31
- '''
31
+ """
32
32
  data = default
33
33
  if os.path.exists(path) and os.access(path, os.R_OK):
34
34
  datafile = None
@@ -62,7 +62,7 @@ def get_file_content(path, default=None, strip=True):
62
62
 
63
63
 
64
64
  def get_file_lines(path, strip=True, line_sep=None):
65
- '''get list of lines from file'''
65
+ """get list of lines from file"""
66
66
  data = get_file_content(path, strip=strip)
67
67
  if data:
68
68
  if line_sep is None:
@@ -18,7 +18,7 @@
18
18
 
19
19
  from __future__ import annotations
20
20
 
21
- import ansible.module_utils.compat.typing as t
21
+ import typing as t
22
22
 
23
23
  from ansible.module_utils.facts.collector import BaseFactCollector
24
24
 
@@ -1,17 +1,5 @@
1
- # This file is part of Ansible
2
- #
3
- # Ansible is free software: you can redistribute it and/or modify
4
- # it under the terms of the GNU General Public License as published by
5
- # the Free Software Foundation, either version 3 of the License, or
6
- # (at your option) any later version.
7
- #
8
- # Ansible is distributed in the hope that it will be useful,
9
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
- # GNU General Public License for more details.
12
- #
13
- # You should have received a copy of the GNU General Public License
14
- # along with Ansible. If not, see <http://www.gnu.org/licenses/>.
1
+ # Copyright: Contributors to the Ansible project
2
+ # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
15
3
 
16
4
  from __future__ import annotations
17
5
 
@@ -77,7 +65,7 @@ class SunOSVirtual(Virtual):
77
65
  if virtinfo:
78
66
  # The output of virtinfo is different whether we are on a machine with logical
79
67
  # domains ('LDoms') on a T-series or domains ('Domains') on a M-series. Try LDoms first.
80
- rc, out, err = self.module.run_command("/usr/sbin/virtinfo -p")
68
+ rc, out, err = self.module.run_command([virtinfo, '-p'])
81
69
  # The output contains multiple lines with different keys like this:
82
70
  # DOMAINROLE|impl=LDoms|control=false|io=false|service=false|root=false
83
71
  # The output may also be not formatted and the returncode is set to 0 regardless of the error condition:
@@ -1,24 +1,11 @@
1
- # This file is part of Ansible
2
- #
3
- # Ansible is free software: you can redistribute it and/or modify
4
- # it under the terms of the GNU General Public License as published by
5
- # the Free Software Foundation, either version 3 of the License, or
6
- # (at your option) any later version.
7
- #
8
- # Ansible is distributed in the hope that it will be useful,
9
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
- # GNU General Public License for more details.
12
- #
13
- # You should have received a copy of the GNU General Public License
14
- # along with Ansible. If not, see <http://www.gnu.org/licenses/>.
15
-
1
+ # Copyright: Contributors to the Ansible project
2
+ # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
16
3
  from __future__ import annotations
17
4
 
18
5
  import re
19
6
 
20
7
 
21
- class VirtualSysctlDetectionMixin(object):
8
+ class VirtualSysctlDetectionMixin:
22
9
  def detect_sysctl(self):
23
10
  self.sysctl_path = self.module.get_bin_path('sysctl')
24
11
 
@@ -32,13 +32,13 @@ import json # pylint: disable=unused-import
32
32
  # NB: a copy of this function exists in ../../modules/core/async_wrapper.py. Ensure any
33
33
  # changes are propagated there.
34
34
  def _filter_non_json_lines(data, objects_only=False):
35
- '''
35
+ """
36
36
  Used to filter unrelated output around module JSON output, like messages from
37
37
  tcagetattr, or where dropbear spews MOTD on every single command (which is nuts).
38
38
 
39
39
  Filters leading lines before first line-starting occurrence of '{' or '[', and filter all
40
40
  trailing lines after matching close character (working from the bottom of output).
41
- '''
41
+ """
42
42
  warnings = []
43
43
 
44
44
  # Filter initial junk
@@ -25,4 +25,4 @@ def boolean(value, strict=True):
25
25
  elif normalized_value in BOOLEANS_FALSE or not strict:
26
26
  return False
27
27
 
28
- raise TypeError("The value '%s' is not a valid boolean. Valid booleans include: %s" % (to_text(value), ', '.join(repr(i) for i in BOOLEANS)))
28
+ raise TypeError("The value '%s' is not a valid boolean. Valid booleans include: %s" % (to_text(value), ', '.join(repr(i) for i in BOOLEANS)))
@@ -35,20 +35,19 @@ import platform
35
35
  import select
36
36
  import shlex
37
37
  import subprocess
38
- import traceback
39
38
 
40
39
  from ansible.module_utils.six import PY2, b
41
40
  from ansible.module_utils.common.text.converters import to_bytes, to_text
42
41
 
43
42
 
44
43
  def sysv_is_enabled(name, runlevel=None):
45
- '''
44
+ """
46
45
  This function will check if the service name supplied
47
46
  is enabled in any of the sysv runlevels
48
47
 
49
48
  :arg name: name of the service to test for
50
49
  :kw runlevel: runlevel to check (default: None)
51
- '''
50
+ """
52
51
  if runlevel:
53
52
  if not os.path.isdir('/etc/rc0.d/'):
54
53
  return bool(glob.glob('/etc/init.d/rc%s.d/S??%s' % (runlevel, name)))
@@ -60,12 +59,12 @@ def sysv_is_enabled(name, runlevel=None):
60
59
 
61
60
 
62
61
  def get_sysv_script(name):
63
- '''
62
+ """
64
63
  This function will return the expected path for an init script
65
64
  corresponding to the service name supplied.
66
65
 
67
66
  :arg name: name or path of the service to test for
68
- '''
67
+ """
69
68
  if name.startswith('/'):
70
69
  result = name
71
70
  else:
@@ -75,19 +74,19 @@ def get_sysv_script(name):
75
74
 
76
75
 
77
76
  def sysv_exists(name):
78
- '''
77
+ """
79
78
  This function will return True or False depending on
80
79
  the existence of an init script corresponding to the service name supplied.
81
80
 
82
81
  :arg name: name of the service to test for
83
- '''
82
+ """
84
83
  return os.path.exists(get_sysv_script(name))
85
84
 
86
85
 
87
86
  def get_ps(module, pattern):
88
- '''
87
+ """
89
88
  Last resort to find a service by trying to match pattern to programs in memory
90
- '''
89
+ """
91
90
  found = False
92
91
  if platform.system() == 'SunOS':
93
92
  flags = '-ef'
@@ -106,7 +105,7 @@ def get_ps(module, pattern):
106
105
 
107
106
 
108
107
  def fail_if_missing(module, found, service, msg=''):
109
- '''
108
+ """
110
109
  This function will return an error or exit gracefully depending on check mode status
111
110
  and if the service is missing or not.
112
111
 
@@ -114,16 +113,16 @@ def fail_if_missing(module, found, service, msg=''):
114
113
  :arg found: boolean indicating if services were found or not
115
114
  :arg service: name of service
116
115
  :kw msg: extra info to append to error/success msg when missing
117
- '''
116
+ """
118
117
  if not found:
119
118
  module.fail_json(msg='Could not find the requested service %s: %s' % (service, msg))
120
119
 
121
120
 
122
121
  def fork_process():
123
- '''
122
+ """
124
123
  This function performs the double fork process to detach from the
125
124
  parent process and execute.
126
- '''
125
+ """
127
126
  pid = os.fork()
128
127
 
129
128
  if pid == 0:
@@ -147,9 +146,7 @@ def fork_process():
147
146
  os._exit(0)
148
147
 
149
148
  # get new process session and detach
150
- sid = os.setsid()
151
- if sid == -1:
152
- raise Exception("Unable to detach session while daemonizing")
149
+ os.setsid()
153
150
 
154
151
  # avoid possible problems with cwd being removed
155
152
  os.chdir("/")
@@ -162,7 +159,7 @@ def fork_process():
162
159
 
163
160
 
164
161
  def daemonize(module, cmd):
165
- '''
162
+ """
166
163
  Execute a command while detaching as a daemon, returns rc, stdout, and stderr.
167
164
 
168
165
  :arg module: is an AnsibleModule object, used for it's utility methods
@@ -171,7 +168,7 @@ def daemonize(module, cmd):
171
168
  This is complex because daemonization is hard for people.
172
169
  What we do is daemonize a part of this module, the daemon runs the command,
173
170
  picks up the return code and output, and returns it to the main process.
174
- '''
171
+ """
175
172
 
176
173
  # init some vars
177
174
  chunk = 4096 # FIXME: pass in as arg?
@@ -181,10 +178,10 @@ def daemonize(module, cmd):
181
178
  try:
182
179
  pipe = os.pipe()
183
180
  pid = fork_process()
184
- except OSError:
185
- module.fail_json(msg="Error while attempting to fork: %s", exception=traceback.format_exc())
181
+ except (OSError, RuntimeError):
182
+ module.fail_json(msg="Error while attempting to fork.")
186
183
  except Exception as exc:
187
- module.fail_json(msg=to_text(exc), exception=traceback.format_exc())
184
+ module.fail_json(msg=to_text(exc))
188
185
 
189
186
  # we don't do any locking as this should be a unique module/process
190
187
  if pid == 0:
@@ -30,10 +30,10 @@ from __future__ import annotations
30
30
 
31
31
 
32
32
  def _get_quote_state(token, quote_char):
33
- '''
33
+ """
34
34
  the goal of this block is to determine if the quoted string
35
35
  is unterminated in which case it needs to be put back together
36
- '''
36
+ """
37
37
  # the char before the current one, used to see if
38
38
  # the current character is escaped
39
39
  prev_char = None
@@ -50,11 +50,11 @@ def _get_quote_state(token, quote_char):
50
50
 
51
51
 
52
52
  def _count_jinja2_blocks(token, cur_depth, open_token, close_token):
53
- '''
53
+ """
54
54
  this function counts the number of opening/closing blocks for a
55
55
  given opening/closing type and adjusts the current depth for that
56
56
  block based on the difference
57
- '''
57
+ """
58
58
  num_open = token.count(open_token)
59
59
  num_close = token.count(close_token)
60
60
  if num_open != num_close:
@@ -65,7 +65,7 @@ def _count_jinja2_blocks(token, cur_depth, open_token, close_token):
65
65
 
66
66
 
67
67
  def split_args(args):
68
- '''
68
+ """
69
69
  Splits args on whitespace, but intelligently reassembles
70
70
  those that may have been split over a jinja2 block or quotes.
71
71
 
@@ -78,7 +78,7 @@ def split_args(args):
78
78
 
79
79
  Basically this is a variation shlex that has some more intelligence for
80
80
  how Ansible needs to use it.
81
- '''
81
+ """
82
82
 
83
83
  # the list of params parsed out of the arg string
84
84
  # this is going to be the result value when we are done
@@ -212,7 +212,7 @@ def is_quoted(data):
212
212
 
213
213
 
214
214
  def unquote(data):
215
- ''' removes first and last quotes from a string, if the string starts and ends with the same quotes '''
215
+ """ removes first and last quotes from a string, if the string starts and ends with the same quotes """
216
216
  if is_quoted(data):
217
217
  return data[1:-1]
218
218
  return data
@@ -0,0 +1,31 @@
1
+ """
2
+ Utilities to support unit testing of Ansible Python modules.
3
+ Not supported for use cases other than testing.
4
+ """
5
+
6
+ from __future__ import annotations as _annotations
7
+
8
+ import contextlib as _contextlib
9
+ import json as _json
10
+ import typing as _t
11
+
12
+ from unittest import mock as _mock
13
+
14
+ from ansible.module_utils.common import json as _common_json
15
+ from . import basic as _basic
16
+
17
+
18
+ @_contextlib.contextmanager
19
+ def patch_module_args(args: dict[str, _t.Any] | None = None) -> _t.Iterator[None]:
20
+ """Expose the given module args to `AnsibleModule` instances created within this context."""
21
+ if not isinstance(args, (dict, type(None))):
22
+ raise TypeError("The `args` arg must be a dict or None.")
23
+
24
+ args = dict(ANSIBLE_MODULE_ARGS=args or {})
25
+ profile = 'legacy' # this should be configurable in the future, once the profile feature is more fully baked
26
+
27
+ encoder = _common_json.get_module_encoder(profile, _common_json.Direction.CONTROLLER_TO_MODULE)
28
+ args = _json.dumps(args, cls=encoder).encode()
29
+
30
+ with _mock.patch.object(_basic, '_ANSIBLE_ARGS', args), _mock.patch.object(_basic, '_ANSIBLE_PROFILE', profile):
31
+ yield
@@ -12,7 +12,7 @@
12
12
  # Simplified BSD License (see licenses/simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause)
13
13
 
14
14
 
15
- '''
15
+ """
16
16
  The **urls** utils module offers a replacement for the urllib python library.
17
17
 
18
18
  urllib is the python stdlib way to retrieve files from the Internet but it
@@ -25,11 +25,12 @@ to replace urllib with a more secure library. However, all third party libraries
25
25
  require that the library be installed on the managed machine. That is an extra step
26
26
  for users making use of a module. If possible, avoid third party libraries by using
27
27
  this code instead.
28
- '''
28
+ """
29
29
 
30
30
  from __future__ import annotations
31
31
 
32
32
  import base64
33
+ import email.encoders
33
34
  import email.mime.application
34
35
  import email.mime.multipart
35
36
  import email.mime.nonmultipart
@@ -223,10 +224,10 @@ UnixHTTPSConnection = None
223
224
  if HAS_SSL:
224
225
  @contextmanager
225
226
  def unix_socket_patch_httpconnection_connect():
226
- '''Monkey patch ``http.client.HTTPConnection.connect`` to be ``UnixHTTPConnection.connect``
227
+ """Monkey patch ``http.client.HTTPConnection.connect`` to be ``UnixHTTPConnection.connect``
227
228
  so that when calling ``super(UnixHTTPSConnection, self).connect()`` we get the
228
229
  correct behavior of creating self.sock for the unix socket
229
- '''
230
+ """
230
231
  _connect = http.client.HTTPConnection.connect
231
232
  http.client.HTTPConnection.connect = UnixHTTPConnection.connect
232
233
  yield
@@ -270,7 +271,7 @@ if HAS_SSL:
270
271
 
271
272
 
272
273
  class UnixHTTPConnection(http.client.HTTPConnection):
273
- '''Handles http requests to a unix socket file'''
274
+ """Handles http requests to a unix socket file"""
274
275
 
275
276
  def __init__(self, unix_socket):
276
277
  self._unix_socket = unix_socket
@@ -290,7 +291,7 @@ class UnixHTTPConnection(http.client.HTTPConnection):
290
291
 
291
292
 
292
293
  class UnixHTTPHandler(urllib.request.HTTPHandler):
293
- '''Handler for Unix urls'''
294
+ """Handler for Unix urls"""
294
295
 
295
296
  def __init__(self, unix_socket, **kwargs):
296
297
  super().__init__(**kwargs)
@@ -301,29 +302,29 @@ class UnixHTTPHandler(urllib.request.HTTPHandler):
301
302
 
302
303
 
303
304
  class ParseResultDottedDict(dict):
304
- '''
305
+ """
305
306
  A dict that acts similarly to the ParseResult named tuple from urllib
306
- '''
307
+ """
307
308
  def __init__(self, *args, **kwargs):
308
309
  super().__init__(*args, **kwargs)
309
310
  self.__dict__ = self
310
311
 
311
312
  def as_list(self):
312
- '''
313
+ """
313
314
  Generate a list from this dict, that looks like the ParseResult named tuple
314
- '''
315
+ """
315
316
  return [self.get(k, None) for k in ('scheme', 'netloc', 'path', 'params', 'query', 'fragment')]
316
317
 
317
318
 
318
319
  def generic_urlparse(parts):
319
- '''
320
+ """
320
321
  Returns a dictionary of url parts as parsed by urlparse,
321
322
  but accounts for the fact that older versions of that
322
323
  library do not support named attributes (ie. .netloc)
323
324
 
324
325
  This method isn't of much use any longer, but is kept
325
326
  in a minimal state for backwards compat.
326
- '''
327
+ """
327
328
  result = ParseResultDottedDict(parts._asdict())
328
329
  result.update({
329
330
  'username': parts.username,
@@ -340,13 +341,16 @@ def extract_pem_certs(data):
340
341
 
341
342
 
342
343
  def get_response_filename(response):
343
- url = response.geturl()
344
- path = urlparse(url)[2]
345
- filename = os.path.basename(path.rstrip('/')) or None
346
- if filename:
347
- filename = unquote(filename)
344
+ if filename := response.headers.get_param('filename', header='content-disposition'):
345
+ filename = os.path.basename(filename)
346
+ else:
347
+ url = response.geturl()
348
+ path = urlparse(url)[2]
349
+ filename = os.path.basename(path.rstrip('/')) or None
350
+ if filename:
351
+ filename = unquote(filename)
348
352
 
349
- return response.headers.get_param('filename', header='content-disposition') or filename
353
+ return filename
350
354
 
351
355
 
352
356
  def parse_content_type(response):
@@ -986,11 +990,11 @@ def open_url(url, data=None, headers=None, method=None, use_proxy=True,
986
990
  client_cert=None, client_key=None, cookies=None,
987
991
  use_gssapi=False, unix_socket=None, ca_path=None,
988
992
  unredirected_headers=None, decompress=True, ciphers=None, use_netrc=True):
989
- '''
993
+ """
990
994
  Sends a request via HTTP(S) or FTP using urllib (Python3)
991
995
 
992
996
  Does not require the module environment
993
- '''
997
+ """
994
998
  method = method or ('POST' if data else 'GET')
995
999
  return Request().open(method, url, data=data, headers=headers, use_proxy=use_proxy,
996
1000
  force=force, last_mod_time=last_mod_time, timeout=timeout, validate_certs=validate_certs,
@@ -1042,6 +1046,7 @@ def prepare_multipart(fields):
1042
1046
  filename = None
1043
1047
  elif isinstance(value, Mapping):
1044
1048
  filename = value.get('filename')
1049
+ multipart_encoding_str = value.get('multipart_encoding') or 'base64'
1045
1050
  content = value.get('content')
1046
1051
  if not any((filename, content)):
1047
1052
  raise ValueError('at least one of filename or content must be provided')
@@ -1053,14 +1058,16 @@ def prepare_multipart(fields):
1053
1058
  except Exception:
1054
1059
  mime = 'application/octet-stream'
1055
1060
  main_type, sep, sub_type = mime.partition('/')
1061
+
1056
1062
  else:
1057
1063
  raise TypeError(
1058
1064
  'value must be a string, or mapping, cannot be type %s' % value.__class__.__name__
1059
1065
  )
1060
1066
 
1061
1067
  if not content and filename:
1068
+ multipart_encoding = set_multipart_encoding(multipart_encoding_str)
1062
1069
  with open(to_bytes(filename, errors='surrogate_or_strict'), 'rb') as f:
1063
- part = email.mime.application.MIMEApplication(f.read())
1070
+ part = email.mime.application.MIMEApplication(f.read(), _encoder=multipart_encoding)
1064
1071
  del part['Content-Type']
1065
1072
  part.add_header('Content-Type', '%s/%s' % (main_type, sub_type))
1066
1073
  else:
@@ -1099,11 +1106,24 @@ def prepare_multipart(fields):
1099
1106
  )
1100
1107
 
1101
1108
 
1109
+ def set_multipart_encoding(encoding):
1110
+ """Takes an string with specific encoding type for multipart data.
1111
+ Will return reference to function from email.encoders library.
1112
+ If given string key doesn't exist it will raise a ValueError"""
1113
+ encoders_dict = {
1114
+ "base64": email.encoders.encode_base64,
1115
+ "7or8bit": email.encoders.encode_7or8bit
1116
+ }
1117
+ if encoders_dict.get(encoding):
1118
+ return encoders_dict.get(encoding)
1119
+ else:
1120
+ raise ValueError("multipart_encoding must be one of %s." % repr(encoders_dict.keys()))
1121
+
1122
+
1102
1123
  #
1103
1124
  # Module-related functions
1104
1125
  #
1105
1126
 
1106
-
1107
1127
  def basic_auth_header(username, password):
1108
1128
  """Takes a username and password and returns a byte string suitable for
1109
1129
  using as value of an Authorization header to do basic auth.
@@ -1114,10 +1134,10 @@ def basic_auth_header(username, password):
1114
1134
 
1115
1135
 
1116
1136
  def url_argument_spec():
1117
- '''
1137
+ """
1118
1138
  Creates an argument spec that can be used with any module
1119
1139
  that will be requesting content via urllib/urllib2
1120
- '''
1140
+ """
1121
1141
  return dict(
1122
1142
  url=dict(type='str'),
1123
1143
  force=dict(type='bool', default=False),
@@ -1133,6 +1153,16 @@ def url_argument_spec():
1133
1153
  )
1134
1154
 
1135
1155
 
1156
+ def url_redirect_argument_spec():
1157
+ """
1158
+ Creates an addition arugment spec to `url_argument_spec`
1159
+ for `follow_redirects` argument
1160
+ """
1161
+ return dict(
1162
+ follow_redirects=dict(type='str', default='safe', choices=['all', 'no', 'none', 'safe', 'urllib2', 'yes']),
1163
+ )
1164
+
1165
+
1136
1166
  def fetch_url(module, url, data=None, headers=None, method=None,
1137
1167
  use_proxy=None, force=False, last_mod_time=None, timeout=10,
1138
1168
  use_gssapi=False, unix_socket=None, ca_path=None, cookies=None, unredirected_headers=None,
@@ -1168,7 +1198,7 @@ def fetch_url(module, url, data=None, headers=None, method=None,
1168
1198
  data={...}
1169
1199
  resp, info = fetch_url(module,
1170
1200
  "http://example.com",
1171
- data=module.jsonify(data),
1201
+ data=json.dumps(data),
1172
1202
  headers={'Content-type': 'application/json'},
1173
1203
  method="POST")
1174
1204
  status_code = info["status"]
@@ -1246,7 +1276,7 @@ def fetch_url(module, url, data=None, headers=None, method=None,
1246
1276
  except (ConnectionError, ValueError) as e:
1247
1277
  module.fail_json(msg=to_native(e), **info)
1248
1278
  except MissingModuleError as e:
1249
- module.fail_json(msg=to_text(e), exception=e.import_traceback)
1279
+ module.fail_json(msg=to_text(e))
1250
1280
  except urllib.error.HTTPError as e:
1251
1281
  r = e
1252
1282
  try:
@@ -1277,9 +1307,8 @@ def fetch_url(module, url, data=None, headers=None, method=None,
1277
1307
  info.update(dict(msg="Connection failure: %s" % to_native(e), status=-1))
1278
1308
  except http.client.BadStatusLine as e:
1279
1309
  info.update(dict(msg="Connection failure: connection was closed before a valid response was received: %s" % to_native(e.line), status=-1))
1280
- except Exception as e:
1281
- info.update(dict(msg="An unknown error occurred: %s" % to_native(e), status=-1),
1282
- exception=traceback.format_exc())
1310
+ except Exception as ex:
1311
+ info.update(dict(msg="An unknown error occurred: %s" % to_native(ex), status=-1, exception=traceback.format_exc()))
1283
1312
  finally:
1284
1313
  tempfile.tempdir = old_tempdir
1285
1314
 
@@ -1330,7 +1359,7 @@ def _split_multiext(name, min=3, max=4, count=2):
1330
1359
  def fetch_file(module, url, data=None, headers=None, method=None,
1331
1360
  use_proxy=True, force=False, last_mod_time=None, timeout=10,
1332
1361
  unredirected_headers=None, decompress=True, ciphers=None):
1333
- '''Download and save a file via HTTP(S) or FTP (needs the module as parameter).
1362
+ """Download and save a file via HTTP(S) or FTP (needs the module as parameter).
1334
1363
  This is basically a wrapper around fetch_url().
1335
1364
 
1336
1365
  :arg module: The AnsibleModule (used to get username, password etc. (s.b.).
@@ -1348,7 +1377,7 @@ def fetch_file(module, url, data=None, headers=None, method=None,
1348
1377
  :kwarg ciphers: (optional) List of ciphers to use
1349
1378
 
1350
1379
  :returns: A string, the path to the downloaded file.
1351
- '''
1380
+ """
1352
1381
  # download file
1353
1382
  bufsize = 65536
1354
1383
  parts = urlparse(url)
@@ -7,7 +7,7 @@
7
7
  from __future__ import annotations
8
8
 
9
9
 
10
- DOCUMENTATION = r'''
10
+ DOCUMENTATION = r"""
11
11
  ---
12
12
  module: add_host
13
13
  short_description: Add a host (and alternatively a group) to the ansible-playbook in-memory inventory
@@ -69,9 +69,9 @@ seealso:
69
69
  author:
70
70
  - Ansible Core Team
71
71
  - Seth Vidal (@skvidal)
72
- '''
72
+ """
73
73
 
74
- EXAMPLES = r'''
74
+ EXAMPLES = r"""
75
75
  - name: Add host to group 'just_created' with variable foo=42
76
76
  ansible.builtin.add_host:
77
77
  name: '{{ ip_from_ec2 }}'
@@ -111,4 +111,4 @@ EXAMPLES = r'''
111
111
  name: '{{ item }}'
112
112
  groups: done
113
113
  loop: "{{ ansible_play_hosts }}"
114
- '''
114
+ """