ansible-core 2.15.4rc1__py3-none-any.whl → 2.16.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.

Potentially problematic release.


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

Files changed (427) hide show
  1. ansible/cli/__init__.py +3 -3
  2. ansible/cli/adhoc.py +1 -1
  3. ansible/cli/arguments/option_helpers.py +15 -5
  4. ansible/cli/config.py +2 -2
  5. ansible/cli/console.py +21 -17
  6. ansible/cli/doc.py +8 -9
  7. ansible/cli/galaxy.py +60 -27
  8. ansible/cli/inventory.py +1 -1
  9. ansible/cli/playbook.py +1 -1
  10. ansible/cli/pull.py +2 -2
  11. ansible/cli/scripts/ansible_connection_cli_stub.py +1 -1
  12. ansible/cli/vault.py +11 -6
  13. ansible/collections/__init__.py +0 -29
  14. ansible/collections/list.py +23 -44
  15. ansible/config/ansible_builtin_runtime.yml +8 -4
  16. ansible/config/base.yml +34 -22
  17. ansible/config/manager.py +1 -1
  18. ansible/constants.py +3 -5
  19. ansible/errors/__init__.py +1 -1
  20. ansible/executor/interpreter_discovery.py +1 -1
  21. ansible/executor/module_common.py +39 -32
  22. ansible/executor/play_iterator.py +0 -15
  23. ansible/executor/playbook_executor.py +3 -3
  24. ansible/executor/powershell/module_manifest.py +1 -1
  25. ansible/executor/powershell/module_wrapper.ps1 +4 -1
  26. ansible/executor/process/worker.py +22 -7
  27. ansible/executor/task_executor.py +39 -40
  28. ansible/executor/task_queue_manager.py +8 -11
  29. ansible/galaxy/__init__.py +1 -1
  30. ansible/galaxy/api.py +8 -11
  31. ansible/galaxy/collection/__init__.py +17 -4
  32. ansible/galaxy/collection/concrete_artifact_manager.py +7 -2
  33. ansible/galaxy/collection/galaxy_api_proxy.py +1 -1
  34. ansible/galaxy/data/container/README.md +3 -5
  35. ansible/galaxy/dependency_resolution/__init__.py +1 -6
  36. ansible/galaxy/dependency_resolution/dataclasses.py +22 -1
  37. ansible/galaxy/dependency_resolution/providers.py +61 -69
  38. ansible/galaxy/role.py +31 -13
  39. ansible/galaxy/token.py +2 -2
  40. ansible/inventory/group.py +1 -1
  41. ansible/inventory/manager.py +1 -1
  42. ansible/module_utils/ansible_release.py +2 -2
  43. ansible/module_utils/basic.py +11 -41
  44. ansible/module_utils/common/file.py +0 -100
  45. ansible/module_utils/common/json.py +1 -1
  46. ansible/module_utils/common/locale.py +1 -1
  47. ansible/module_utils/common/text/converters.py +2 -2
  48. ansible/module_utils/common/validation.py +1 -1
  49. ansible/module_utils/compat/_selectors2.py +4 -4
  50. ansible/module_utils/compat/datetime.py +40 -0
  51. ansible/module_utils/compat/selinux.py +1 -1
  52. ansible/module_utils/compat/typing.py +1 -1
  53. ansible/module_utils/connection.py +1 -1
  54. ansible/module_utils/facts/hardware/linux.py +2 -2
  55. ansible/module_utils/facts/hardware/openbsd.py +1 -1
  56. ansible/module_utils/facts/network/linux.py +3 -3
  57. ansible/module_utils/facts/other/facter.py +8 -15
  58. ansible/module_utils/facts/sysctl.py +1 -1
  59. ansible/module_utils/facts/system/date_time.py +2 -2
  60. ansible/module_utils/facts/system/distribution.py +1 -1
  61. ansible/module_utils/facts/system/local.py +6 -2
  62. ansible/module_utils/facts/system/pkg_mgr.py +6 -1
  63. ansible/module_utils/facts/system/service_mgr.py +4 -2
  64. ansible/module_utils/parsing/convert_bool.py +1 -1
  65. ansible/module_utils/service.py +9 -6
  66. ansible/module_utils/urls.py +40 -22
  67. ansible/modules/add_host.py +2 -2
  68. ansible/modules/apt.py +48 -31
  69. ansible/modules/apt_key.py +4 -4
  70. ansible/modules/apt_repository.py +5 -5
  71. ansible/modules/assemble.py +7 -7
  72. ansible/modules/assert.py +1 -1
  73. ansible/modules/async_status.py +11 -7
  74. ansible/modules/async_wrapper.py +1 -1
  75. ansible/modules/blockinfile.py +60 -17
  76. ansible/modules/command.py +37 -15
  77. ansible/modules/copy.py +35 -30
  78. ansible/modules/cron.py +14 -14
  79. ansible/modules/deb822_repository.py +4 -3
  80. ansible/modules/debconf.py +35 -14
  81. ansible/modules/debug.py +1 -1
  82. ansible/modules/dnf.py +29 -27
  83. ansible/modules/dnf5.py +22 -22
  84. ansible/modules/dpkg_selections.py +9 -2
  85. ansible/modules/expect.py +4 -4
  86. ansible/modules/fetch.py +7 -7
  87. ansible/modules/file.py +30 -30
  88. ansible/modules/find.py +82 -22
  89. ansible/modules/gather_facts.py +6 -2
  90. ansible/modules/get_url.py +29 -29
  91. ansible/modules/getent.py +4 -4
  92. ansible/modules/git.py +27 -27
  93. ansible/modules/group.py +5 -12
  94. ansible/modules/hostname.py +21 -2
  95. ansible/modules/include_role.py +5 -5
  96. ansible/modules/include_tasks.py +2 -2
  97. ansible/modules/include_vars.py +5 -5
  98. ansible/modules/iptables.py +70 -65
  99. ansible/modules/known_hosts.py +7 -7
  100. ansible/modules/lineinfile.py +33 -33
  101. ansible/modules/meta.py +13 -13
  102. ansible/modules/package.py +8 -8
  103. ansible/modules/package_facts.py +3 -3
  104. ansible/modules/pause.py +2 -2
  105. ansible/modules/ping.py +5 -5
  106. ansible/modules/pip.py +80 -46
  107. ansible/modules/reboot.py +8 -4
  108. ansible/modules/replace.py +20 -15
  109. ansible/modules/rpm_key.py +2 -2
  110. ansible/modules/script.py +16 -10
  111. ansible/modules/service.py +26 -98
  112. ansible/modules/service_facts.py +36 -12
  113. ansible/modules/set_fact.py +2 -2
  114. ansible/modules/set_stats.py +2 -2
  115. ansible/modules/setup.py +18 -18
  116. ansible/modules/shell.py +3 -3
  117. ansible/modules/stat.py +9 -30
  118. ansible/modules/subversion.py +9 -9
  119. ansible/modules/systemd.py +20 -19
  120. ansible/modules/systemd_service.py +20 -19
  121. ansible/modules/sysvinit.py +26 -21
  122. ansible/modules/tempfile.py +5 -4
  123. ansible/modules/template.py +60 -6
  124. ansible/modules/unarchive.py +21 -18
  125. ansible/modules/uri.py +39 -39
  126. ansible/modules/user.py +81 -53
  127. ansible/modules/wait_for.py +22 -21
  128. ansible/modules/wait_for_connection.py +4 -4
  129. ansible/modules/yum.py +38 -38
  130. ansible/modules/yum_repository.py +58 -80
  131. ansible/parsing/dataloader.py +27 -27
  132. ansible/parsing/mod_args.py +1 -1
  133. ansible/parsing/plugin_docs.py +3 -3
  134. ansible/parsing/splitter.py +14 -16
  135. ansible/parsing/utils/yaml.py +1 -1
  136. ansible/parsing/vault/__init__.py +8 -6
  137. ansible/parsing/yaml/constructor.py +1 -1
  138. ansible/parsing/yaml/objects.py +1 -1
  139. ansible/playbook/__init__.py +1 -1
  140. ansible/playbook/base.py +2 -2
  141. ansible/playbook/block.py +0 -1
  142. ansible/playbook/conditional.py +40 -114
  143. ansible/playbook/helpers.py +5 -28
  144. ansible/playbook/included_file.py +8 -7
  145. ansible/playbook/play.py +1 -1
  146. ansible/playbook/play_context.py +2 -2
  147. ansible/playbook/playbook_include.py +2 -2
  148. ansible/playbook/role/__init__.py +1 -1
  149. ansible/playbook/role/include.py +1 -1
  150. ansible/playbook/role/metadata.py +1 -1
  151. ansible/playbook/role_include.py +1 -1
  152. ansible/playbook/task.py +2 -2
  153. ansible/playbook/task_include.py +1 -24
  154. ansible/plugins/__init__.py +13 -5
  155. ansible/plugins/action/__init__.py +17 -43
  156. ansible/plugins/action/add_host.py +2 -3
  157. ansible/plugins/action/assemble.py +1 -1
  158. ansible/plugins/action/assert.py +2 -1
  159. ansible/plugins/action/copy.py +2 -2
  160. ansible/plugins/action/debug.py +2 -1
  161. ansible/plugins/action/fail.py +1 -0
  162. ansible/plugins/action/fetch.py +3 -1
  163. ansible/plugins/action/gather_facts.py +37 -13
  164. ansible/plugins/action/group_by.py +1 -0
  165. ansible/plugins/action/include_vars.py +3 -2
  166. ansible/plugins/action/normal.py +3 -3
  167. ansible/plugins/action/pause.py +1 -1
  168. ansible/plugins/action/reboot.py +21 -16
  169. ansible/plugins/action/script.py +23 -8
  170. ansible/plugins/action/set_fact.py +1 -0
  171. ansible/plugins/action/set_stats.py +1 -0
  172. ansible/plugins/action/shell.py +6 -0
  173. ansible/plugins/action/template.py +1 -1
  174. ansible/plugins/action/unarchive.py +1 -1
  175. ansible/plugins/action/uri.py +1 -1
  176. ansible/plugins/action/validate_argument_spec.py +1 -0
  177. ansible/plugins/action/wait_for_connection.py +4 -4
  178. ansible/plugins/become/__init__.py +1 -1
  179. ansible/plugins/become/su.py +1 -1
  180. ansible/plugins/cache/__init__.py +1 -1
  181. ansible/plugins/callback/junit.py +1 -1
  182. ansible/plugins/callback/oneline.py +1 -1
  183. ansible/plugins/callback/tree.py +1 -1
  184. ansible/plugins/cliconf/__init__.py +2 -2
  185. ansible/plugins/connection/__init__.py +65 -37
  186. ansible/plugins/connection/local.py +9 -8
  187. ansible/plugins/connection/paramiko_ssh.py +34 -28
  188. ansible/plugins/connection/psrp.py +56 -43
  189. ansible/plugins/connection/ssh.py +67 -43
  190. ansible/plugins/connection/winrm.py +77 -30
  191. ansible/plugins/doc_fragments/constructed.py +4 -4
  192. ansible/plugins/doc_fragments/files.py +12 -12
  193. ansible/plugins/doc_fragments/inventory_cache.py +0 -6
  194. ansible/plugins/doc_fragments/result_format_callback.py +5 -5
  195. ansible/plugins/doc_fragments/shell_common.py +2 -2
  196. ansible/plugins/doc_fragments/shell_windows.py +1 -1
  197. ansible/plugins/doc_fragments/template_common.py +6 -6
  198. ansible/plugins/doc_fragments/url.py +10 -10
  199. ansible/plugins/doc_fragments/url_windows.py +15 -15
  200. ansible/plugins/doc_fragments/vars_plugin_staging.py +4 -4
  201. ansible/plugins/filter/b64decode.yml +1 -1
  202. ansible/plugins/filter/b64encode.yml +2 -2
  203. ansible/plugins/filter/bool.yml +5 -5
  204. ansible/plugins/filter/combine.yml +1 -1
  205. ansible/plugins/filter/commonpath.yml +2 -1
  206. ansible/plugins/filter/core.py +6 -8
  207. ansible/plugins/filter/dict2items.yml +11 -1
  208. ansible/plugins/filter/difference.yml +1 -0
  209. ansible/plugins/filter/encryption.py +1 -1
  210. ansible/plugins/filter/extract.yml +1 -1
  211. ansible/plugins/filter/flatten.yml +1 -1
  212. ansible/plugins/filter/from_yaml.yml +1 -1
  213. ansible/plugins/filter/from_yaml_all.yml +2 -2
  214. ansible/plugins/filter/hash.yml +1 -1
  215. ansible/plugins/filter/human_readable.yml +1 -1
  216. ansible/plugins/filter/human_to_bytes.yml +2 -2
  217. ansible/plugins/filter/intersect.yml +1 -0
  218. ansible/plugins/filter/mandatory.yml +7 -0
  219. ansible/plugins/filter/mathstuff.py +15 -17
  220. ansible/plugins/filter/normpath.yml +1 -1
  221. ansible/plugins/filter/path_join.yml +8 -1
  222. ansible/plugins/filter/realpath.yml +3 -2
  223. ansible/plugins/filter/regex_findall.yml +8 -2
  224. ansible/plugins/filter/regex_replace.yml +9 -3
  225. ansible/plugins/filter/regex_search.yml +8 -2
  226. ansible/plugins/filter/relpath.yml +2 -2
  227. ansible/plugins/filter/root.yml +1 -1
  228. ansible/plugins/filter/splitext.yml +1 -1
  229. ansible/plugins/filter/subelements.yml +2 -2
  230. ansible/plugins/filter/symmetric_difference.yml +1 -0
  231. ansible/plugins/filter/ternary.yml +5 -5
  232. ansible/plugins/filter/to_json.yml +7 -7
  233. ansible/plugins/filter/to_nice_json.yml +5 -5
  234. ansible/plugins/filter/to_yaml.yml +2 -2
  235. ansible/plugins/filter/type_debug.yml +1 -1
  236. ansible/plugins/filter/union.yml +1 -0
  237. ansible/plugins/filter/unvault.yml +2 -2
  238. ansible/plugins/filter/urldecode.yml +13 -32
  239. ansible/plugins/filter/urlsplit.py +1 -1
  240. ansible/plugins/filter/vault.yml +1 -1
  241. ansible/plugins/filter/zip.yml +1 -1
  242. ansible/plugins/filter/zip_longest.yml +1 -1
  243. ansible/plugins/inventory/__init__.py +1 -1
  244. ansible/plugins/inventory/advanced_host_list.py +1 -1
  245. ansible/plugins/inventory/constructed.py +2 -2
  246. ansible/plugins/inventory/host_list.py +1 -1
  247. ansible/plugins/inventory/ini.py +6 -3
  248. ansible/plugins/inventory/script.py +8 -2
  249. ansible/plugins/inventory/toml.py +1 -1
  250. ansible/plugins/inventory/yaml.py +1 -1
  251. ansible/plugins/list.py +21 -17
  252. ansible/plugins/loader.py +66 -88
  253. ansible/plugins/lookup/__init__.py +1 -1
  254. ansible/plugins/lookup/config.py +16 -6
  255. ansible/plugins/lookup/csvfile.py +7 -4
  256. ansible/plugins/lookup/env.py +1 -1
  257. ansible/plugins/lookup/file.py +5 -2
  258. ansible/plugins/lookup/fileglob.py +5 -2
  259. ansible/plugins/lookup/first_found.py +20 -14
  260. ansible/plugins/lookup/ini.py +6 -3
  261. ansible/plugins/lookup/lines.py +2 -1
  262. ansible/plugins/lookup/password.py +7 -7
  263. ansible/plugins/lookup/pipe.py +1 -0
  264. ansible/plugins/lookup/random_choice.py +2 -2
  265. ansible/plugins/lookup/sequence.py +1 -1
  266. ansible/plugins/lookup/subelements.py +2 -2
  267. ansible/plugins/lookup/template.py +4 -1
  268. ansible/plugins/lookup/unvault.py +4 -1
  269. ansible/plugins/lookup/url.py +6 -6
  270. ansible/plugins/lookup/varnames.py +1 -1
  271. ansible/plugins/netconf/__init__.py +3 -3
  272. ansible/plugins/shell/__init__.py +1 -1
  273. ansible/plugins/shell/cmd.py +7 -7
  274. ansible/plugins/shell/powershell.py +1 -1
  275. ansible/plugins/strategy/__init__.py +8 -10
  276. ansible/plugins/strategy/free.py +1 -1
  277. ansible/plugins/strategy/linear.py +3 -3
  278. ansible/plugins/terminal/__init__.py +2 -2
  279. ansible/plugins/test/abs.yml +1 -1
  280. ansible/plugins/test/all.yml +1 -1
  281. ansible/plugins/test/any.yml +1 -1
  282. ansible/plugins/test/change.yml +2 -2
  283. ansible/plugins/test/changed.yml +2 -2
  284. ansible/plugins/test/contains.yml +1 -1
  285. ansible/plugins/test/core.py +1 -1
  286. ansible/plugins/test/directory.yml +1 -1
  287. ansible/plugins/test/exists.yml +3 -2
  288. ansible/plugins/test/failed.yml +2 -2
  289. ansible/plugins/test/failure.yml +2 -2
  290. ansible/plugins/test/falsy.yml +2 -2
  291. ansible/plugins/test/file.yml +1 -1
  292. ansible/plugins/test/finished.yml +2 -2
  293. ansible/plugins/test/is_abs.yml +1 -1
  294. ansible/plugins/test/is_dir.yml +1 -1
  295. ansible/plugins/test/is_file.yml +1 -1
  296. ansible/plugins/test/is_link.yml +1 -1
  297. ansible/plugins/test/is_mount.yml +1 -1
  298. ansible/plugins/test/is_same_file.yml +1 -1
  299. ansible/plugins/test/isnan.yml +1 -1
  300. ansible/plugins/test/issubset.yml +1 -2
  301. ansible/plugins/test/issuperset.yml +1 -2
  302. ansible/plugins/test/link.yml +1 -1
  303. ansible/plugins/test/link_exists.yml +1 -1
  304. ansible/plugins/test/match.yml +2 -2
  305. ansible/plugins/test/mount.yml +1 -1
  306. ansible/plugins/test/nan.yml +1 -1
  307. ansible/plugins/test/reachable.yml +2 -2
  308. ansible/plugins/test/regex.yml +1 -1
  309. ansible/plugins/test/same_file.yml +1 -1
  310. ansible/plugins/test/search.yml +2 -2
  311. ansible/plugins/test/skip.yml +3 -3
  312. ansible/plugins/test/skipped.yml +3 -3
  313. ansible/plugins/test/started.yml +2 -2
  314. ansible/plugins/test/subset.yml +1 -2
  315. ansible/plugins/test/succeeded.yml +2 -2
  316. ansible/plugins/test/success.yml +2 -2
  317. ansible/plugins/test/successful.yml +2 -2
  318. ansible/plugins/test/superset.yml +1 -2
  319. ansible/plugins/test/truthy.yml +3 -3
  320. ansible/plugins/test/unreachable.yml +2 -2
  321. ansible/plugins/test/uri.yml +1 -1
  322. ansible/plugins/test/url.yml +1 -1
  323. ansible/plugins/test/urn.yml +1 -1
  324. ansible/plugins/test/vault_encrypted.yml +1 -1
  325. ansible/plugins/test/version.yml +7 -7
  326. ansible/plugins/test/version_compare.yml +7 -7
  327. ansible/plugins/vars/host_group_vars.py +1 -1
  328. ansible/release.py +2 -2
  329. ansible/template/__init__.py +24 -26
  330. ansible/template/native_helpers.py +1 -1
  331. ansible/template/vars.py +1 -1
  332. ansible/utils/_junit_xml.py +1 -1
  333. ansible/utils/cmd_functions.py +1 -1
  334. ansible/utils/collection_loader/_collection_finder.py +12 -1
  335. ansible/utils/display.py +113 -62
  336. ansible/utils/encrypt.py +11 -14
  337. ansible/utils/hashing.py +1 -1
  338. ansible/utils/jsonrpc.py +1 -1
  339. ansible/utils/path.py +1 -1
  340. ansible/utils/plugin_docs.py +1 -1
  341. ansible/utils/py3compat.py +1 -1
  342. ansible/utils/shlex.py +2 -10
  343. ansible/utils/ssh_functions.py +5 -4
  344. ansible/utils/unicode.py +1 -1
  345. ansible/utils/unsafe_proxy.py +1 -1
  346. ansible/utils/vars.py +4 -29
  347. ansible/vars/hostvars.py +1 -2
  348. ansible/vars/manager.py +13 -9
  349. ansible/vars/plugins.py +2 -2
  350. {ansible_core-2.15.4rc1.dist-info → ansible_core-2.16.0b2.dist-info}/COPYING +4 -5
  351. {ansible_core-2.15.4rc1.dist-info → ansible_core-2.16.0b2.dist-info}/METADATA +2 -4
  352. {ansible_core-2.15.4rc1.dist-info → ansible_core-2.16.0b2.dist-info}/RECORD +424 -425
  353. ansible_test/_data/completion/docker.txt +9 -9
  354. ansible_test/_data/completion/remote.txt +4 -7
  355. ansible_test/_data/completion/windows.txt +0 -2
  356. ansible_test/_data/requirements/ansible-test.txt +2 -1
  357. ansible_test/_data/requirements/ansible.txt +0 -3
  358. ansible_test/_data/requirements/constraints.txt +0 -2
  359. ansible_test/_data/requirements/sanity.ansible-doc.txt +3 -5
  360. ansible_test/_data/requirements/sanity.changelog.in +1 -2
  361. ansible_test/_data/requirements/sanity.changelog.txt +4 -6
  362. ansible_test/_data/requirements/sanity.import.plugin.txt +2 -4
  363. ansible_test/_data/requirements/sanity.import.txt +1 -3
  364. ansible_test/_data/requirements/sanity.integration-aliases.txt +1 -3
  365. ansible_test/_data/requirements/sanity.mypy.txt +12 -12
  366. ansible_test/_data/requirements/sanity.pep8.txt +1 -1
  367. ansible_test/_data/requirements/sanity.pylint.txt +6 -12
  368. ansible_test/_data/requirements/sanity.runtime-metadata.txt +1 -3
  369. ansible_test/_data/requirements/sanity.validate-modules.in +1 -1
  370. ansible_test/_data/requirements/sanity.validate-modules.txt +3 -5
  371. ansible_test/_data/requirements/sanity.yamllint.txt +3 -5
  372. ansible_test/_data/requirements/units.txt +0 -1
  373. ansible_test/_internal/ci/azp.py +4 -4
  374. ansible_test/_internal/cli/environments.py +0 -13
  375. ansible_test/_internal/commands/coverage/analyze/targets/__init__.py +4 -4
  376. ansible_test/_internal/commands/coverage/combine.py +1 -1
  377. ansible_test/_internal/commands/integration/cloud/acme.py +6 -8
  378. ansible_test/_internal/commands/integration/cloud/cs.py +4 -9
  379. ansible_test/_internal/commands/integration/cloud/galaxy.py +103 -96
  380. ansible_test/_internal/commands/integration/cloud/httptester.py +0 -3
  381. ansible_test/_internal/commands/integration/cloud/nios.py +7 -9
  382. ansible_test/_internal/commands/integration/cloud/openshift.py +2 -7
  383. ansible_test/_internal/commands/integration/cloud/vcenter.py +11 -95
  384. ansible_test/_internal/commands/sanity/__init__.py +10 -0
  385. ansible_test/_internal/commands/sanity/import.py +8 -2
  386. ansible_test/_internal/commands/sanity/pylint.py +27 -1
  387. ansible_test/_internal/commands/units/__init__.py +2 -1
  388. ansible_test/_internal/config.py +0 -7
  389. ansible_test/_internal/containers.py +11 -56
  390. ansible_test/_internal/core_ci.py +0 -7
  391. ansible_test/_internal/coverage_util.py +8 -3
  392. ansible_test/_internal/delegation.py +0 -1
  393. ansible_test/_internal/diff.py +1 -1
  394. ansible_test/_internal/docker_util.py +9 -2
  395. ansible_test/_internal/host_profiles.py +6 -6
  396. ansible_test/_internal/http.py +1 -1
  397. ansible_test/_internal/junit_xml.py +1 -1
  398. ansible_test/_internal/pypi_proxy.py +1 -1
  399. ansible_test/_internal/python_requirements.py +3 -8
  400. ansible_test/_internal/util.py +1 -6
  401. ansible_test/_util/controller/sanity/code-smell/no-get-exception.json +4 -0
  402. ansible_test/_util/controller/sanity/code-smell/replace-urlopen.json +4 -0
  403. ansible_test/_util/controller/sanity/code-smell/use-compat-six.json +4 -0
  404. ansible_test/_util/controller/sanity/mypy/ansible-core.ini +3 -0
  405. ansible_test/_util/controller/sanity/pylint/config/ansible-test-target.cfg +2 -0
  406. ansible_test/_util/controller/sanity/pylint/config/ansible-test.cfg +0 -1
  407. ansible_test/_util/controller/sanity/pylint/config/collection.cfg +1 -0
  408. ansible_test/_util/controller/sanity/pylint/plugins/deprecated.py +172 -10
  409. ansible_test/_util/controller/sanity/pylint/plugins/string_format.py +13 -2
  410. ansible_test/_util/controller/sanity/pylint/plugins/unwanted.py +7 -1
  411. ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py +6 -6
  412. ansible_test/_util/controller/sanity/validate-modules/validate_modules/module_args.py +1 -1
  413. ansible_test/_util/controller/sanity/validate-modules/validate_modules/utils.py +1 -1
  414. ansible_test/_util/controller/sanity/yamllint/yamllinter.py +3 -3
  415. ansible_test/_util/controller/tools/collection_detail.py +2 -2
  416. ansible_test/_util/target/common/constants.py +2 -2
  417. ansible_test/_util/target/pytest/plugins/ansible_forked.py +103 -0
  418. ansible_test/_util/target/sanity/import/importer.py +0 -8
  419. ansible_test/_util/target/setup/bootstrap.sh +36 -16
  420. ansible_test/_util/target/setup/quiet_pip.py +0 -4
  421. ansible/modules/_include.py +0 -80
  422. ansible_test/_internal/commands/integration/cloud/foreman.py +0 -102
  423. ansible_test/_util/target/setup/ConfigureRemotingForAnsible.ps1 +0 -435
  424. {ansible_core-2.15.4rc1.data → ansible_core-2.16.0b2.data}/scripts/ansible-test +0 -0
  425. {ansible_core-2.15.4rc1.dist-info → ansible_core-2.16.0b2.dist-info}/WHEEL +0 -0
  426. {ansible_core-2.15.4rc1.dist-info → ansible_core-2.16.0b2.dist-info}/entry_points.txt +0 -0
  427. {ansible_core-2.15.4rc1.dist-info → ansible_core-2.16.0b2.dist-info}/top_level.txt +0 -0
@@ -22,7 +22,7 @@ import os
22
22
 
23
23
  from ansible import constants as C
24
24
  from ansible.errors import AnsibleParserError, AnsibleUndefinedVariable, AnsibleAssertionError
25
- from ansible.module_utils._text import to_native
25
+ from ansible.module_utils.common.text.converters import to_native
26
26
  from ansible.parsing.mod_args import ModuleArgsParser
27
27
  from ansible.utils.display import Display
28
28
 
@@ -150,23 +150,9 @@ def load_list_of_tasks(ds, play, block=None, role=None, task_include=None, use_h
150
150
  templar = Templar(loader=loader, variables=all_vars)
151
151
 
152
152
  # check to see if this include is dynamic or static:
153
- # 1. the user has set the 'static' option to false or true
154
- # 2. one of the appropriate config options was set
155
- if action in C._ACTION_INCLUDE_TASKS:
156
- is_static = False
157
- elif action in C._ACTION_IMPORT_TASKS:
158
- is_static = True
159
- else:
160
- include_link = get_versioned_doclink('user_guide/playbooks_reuse_includes.html')
161
- display.deprecated('"include" is deprecated, use include_tasks/import_tasks instead. See %s for details' % include_link, "2.16")
162
- is_static = not templar.is_template(t.args['_raw_params']) and t.all_parents_static() and not t.loop
163
-
164
- if is_static:
153
+ if action in C._ACTION_IMPORT_TASKS:
165
154
  if t.loop is not None:
166
- if action in C._ACTION_IMPORT_TASKS:
167
- raise AnsibleParserError("You cannot use loops on 'import_tasks' statements. You should use 'include_tasks' instead.", obj=task_ds)
168
- else:
169
- raise AnsibleParserError("You cannot use 'static' on an include with a loop", obj=task_ds)
155
+ raise AnsibleParserError("You cannot use loops on 'import_tasks' statements. You should use 'include_tasks' instead.", obj=task_ds)
170
156
 
171
157
  # we set a flag to indicate this include was static
172
158
  t.statically_loaded = True
@@ -288,18 +274,9 @@ def load_list_of_tasks(ds, play, block=None, role=None, task_include=None, use_h
288
274
  loader=loader,
289
275
  )
290
276
 
291
- # 1. the user has set the 'static' option to false or true
292
- # 2. one of the appropriate config options was set
293
- is_static = False
294
277
  if action in C._ACTION_IMPORT_ROLE:
295
- is_static = True
296
-
297
- if is_static:
298
278
  if ir.loop is not None:
299
- if action in C._ACTION_IMPORT_ROLE:
300
- raise AnsibleParserError("You cannot use loops on 'import_role' statements. You should use 'include_role' instead.", obj=task_ds)
301
- else:
302
- raise AnsibleParserError("You cannot use 'static' on an include_role with a loop", obj=task_ds)
279
+ raise AnsibleParserError("You cannot use loops on 'import_role' statements. You should use 'include_role' instead.", obj=task_ds)
303
280
 
304
281
  # we set a flag to indicate this include was static
305
282
  ir.statically_loaded = True
@@ -311,7 +288,7 @@ def load_list_of_tasks(ds, play, block=None, role=None, task_include=None, use_h
311
288
  ir._role_name = templar.template(ir._role_name)
312
289
 
313
290
  # uses compiled list from object
314
- blocks, _ = ir.get_block_list(variable_manager=variable_manager, loader=loader)
291
+ blocks, dummy = ir.get_block_list(variable_manager=variable_manager, loader=loader)
315
292
  task_list.extend(blocks)
316
293
  else:
317
294
  # passes task object itself for latter generation of list
@@ -24,7 +24,7 @@ import os
24
24
  from ansible import constants as C
25
25
  from ansible.errors import AnsibleError
26
26
  from ansible.executor.task_executor import remove_omit
27
- from ansible.module_utils._text import to_text
27
+ from ansible.module_utils.common.text.converters import to_text
28
28
  from ansible.playbook.handler import Handler
29
29
  from ansible.playbook.task_include import TaskInclude
30
30
  from ansible.playbook.role_include import IncludeRole
@@ -72,8 +72,6 @@ class IncludedFile:
72
72
  original_task = res._task
73
73
 
74
74
  if original_task.action in C._ACTION_ALL_INCLUDES:
75
- if original_task.action in C._ACTION_INCLUDE:
76
- display.deprecated('"include" is deprecated, use include_tasks/import_tasks/import_playbook instead', "2.16")
77
75
 
78
76
  if original_task.loop:
79
77
  if 'results' not in res._result:
@@ -118,7 +116,7 @@ class IncludedFile:
118
116
 
119
117
  templar = Templar(loader=loader, variables=task_vars)
120
118
 
121
- if original_task.action in C._ACTION_ALL_INCLUDE_TASKS:
119
+ if original_task.action in C._ACTION_INCLUDE_TASKS:
122
120
  include_file = None
123
121
 
124
122
  if original_task._parent:
@@ -148,9 +146,12 @@ class IncludedFile:
148
146
  cumulative_path = parent_include_dir
149
147
  include_target = templar.template(include_result['include'])
150
148
  if original_task._role:
151
- new_basedir = os.path.join(original_task._role._role_path, 'tasks', cumulative_path)
152
- candidates = [loader.path_dwim_relative(original_task._role._role_path, 'tasks', include_target),
153
- loader.path_dwim_relative(new_basedir, 'tasks', include_target)]
149
+ dirname = 'handlers' if isinstance(original_task, Handler) else 'tasks'
150
+ new_basedir = os.path.join(original_task._role._role_path, dirname, cumulative_path)
151
+ candidates = [
152
+ loader.path_dwim_relative(original_task._role._role_path, dirname, include_target),
153
+ loader.path_dwim_relative(new_basedir, dirname, include_target)
154
+ ]
154
155
  for include_file in candidates:
155
156
  try:
156
157
  # may throw OSError
ansible/playbook/play.py CHANGED
@@ -22,7 +22,7 @@ __metaclass__ = type
22
22
  from ansible import constants as C
23
23
  from ansible import context
24
24
  from ansible.errors import AnsibleParserError, AnsibleAssertionError
25
- from ansible.module_utils._text import to_native
25
+ from ansible.module_utils.common.text.converters import to_native
26
26
  from ansible.module_utils.common.collections import is_sequence
27
27
  from ansible.module_utils.six import binary_type, string_types, text_type
28
28
  from ansible.playbook.attribute import NonInheritableFieldAttribute
@@ -119,7 +119,7 @@ class PlayContext(Base):
119
119
  def verbosity(self):
120
120
  display.deprecated(
121
121
  "PlayContext.verbosity is deprecated, use ansible.utils.display.Display.verbosity instead.",
122
- version=2.18
122
+ version="2.18"
123
123
  )
124
124
  return self._internal_verbosity
125
125
 
@@ -127,7 +127,7 @@ class PlayContext(Base):
127
127
  def verbosity(self, value):
128
128
  display.deprecated(
129
129
  "PlayContext.verbosity is deprecated, use ansible.utils.display.Display.verbosity instead.",
130
- version=2.18
130
+ version="2.18"
131
131
  )
132
132
  self._internal_verbosity = value
133
133
 
@@ -23,7 +23,7 @@ import os
23
23
 
24
24
  import ansible.constants as C
25
25
  from ansible.errors import AnsibleParserError, AnsibleAssertionError
26
- from ansible.module_utils._text import to_bytes
26
+ from ansible.module_utils.common.text.converters import to_bytes
27
27
  from ansible.module_utils.six import string_types
28
28
  from ansible.parsing.splitter import split_args
29
29
  from ansible.parsing.yaml.objects import AnsibleBaseYAMLObject, AnsibleMapping
@@ -48,7 +48,7 @@ class PlaybookInclude(Base, Conditional, Taggable):
48
48
  def load(data, basedir, variable_manager=None, loader=None):
49
49
  return PlaybookInclude().load_data(ds=data, basedir=basedir, variable_manager=variable_manager, loader=loader)
50
50
 
51
- def load_data(self, ds, basedir, variable_manager=None, loader=None):
51
+ def load_data(self, ds, variable_manager=None, loader=None, basedir=None):
52
52
  '''
53
53
  Overrides the base load_data(), as we're actually going to return a new
54
54
  Playbook() object rather than a PlaybookInclude object
@@ -26,7 +26,7 @@ from types import MappingProxyType
26
26
 
27
27
  from ansible import constants as C
28
28
  from ansible.errors import AnsibleError, AnsibleParserError, AnsibleAssertionError
29
- from ansible.module_utils._text import to_text
29
+ from ansible.module_utils.common.text.converters import to_text
30
30
  from ansible.module_utils.six import binary_type, text_type
31
31
  from ansible.playbook.attribute import FieldAttribute
32
32
  from ansible.playbook.base import Base
@@ -24,7 +24,7 @@ from ansible.module_utils.six import string_types
24
24
  from ansible.parsing.yaml.objects import AnsibleBaseYAMLObject
25
25
  from ansible.playbook.delegatable import Delegatable
26
26
  from ansible.playbook.role.definition import RoleDefinition
27
- from ansible.module_utils._text import to_native
27
+ from ansible.module_utils.common.text.converters import to_native
28
28
 
29
29
 
30
30
  __all__ = ['RoleInclude']
@@ -22,7 +22,7 @@ __metaclass__ = type
22
22
  import os
23
23
 
24
24
  from ansible.errors import AnsibleParserError, AnsibleError
25
- from ansible.module_utils._text import to_native
25
+ from ansible.module_utils.common.text.converters import to_native
26
26
  from ansible.module_utils.six import string_types
27
27
  from ansible.playbook.attribute import NonInheritableFieldAttribute
28
28
  from ansible.playbook.base import Base
@@ -49,10 +49,10 @@ class IncludeRole(TaskInclude):
49
49
 
50
50
  # =================================================================================
51
51
  # ATTRIBUTES
52
+ public = NonInheritableFieldAttribute(isa='bool', default=None, private=False, always_post_validate=True)
52
53
 
53
54
  # private as this is a 'module options' vs a task property
54
55
  allow_duplicates = NonInheritableFieldAttribute(isa='bool', default=True, private=True, always_post_validate=True)
55
- public = NonInheritableFieldAttribute(isa='bool', default=False, private=True, always_post_validate=True)
56
56
  rolespec_validate = NonInheritableFieldAttribute(isa='bool', default=True, private=True, always_post_validate=True)
57
57
 
58
58
  def __init__(self, block=None, role=None, task_include=None):
ansible/playbook/task.py CHANGED
@@ -21,7 +21,7 @@ __metaclass__ = type
21
21
 
22
22
  from ansible import constants as C
23
23
  from ansible.errors import AnsibleError, AnsibleParserError, AnsibleUndefinedVariable, AnsibleAssertionError
24
- from ansible.module_utils._text import to_native
24
+ from ansible.module_utils.common.text.converters import to_native
25
25
  from ansible.module_utils.six import string_types
26
26
  from ansible.parsing.mod_args import ModuleArgsParser
27
27
  from ansible.parsing.yaml.objects import AnsibleBaseYAMLObject, AnsibleMapping
@@ -79,7 +79,7 @@ class Task(Base, Conditional, Taggable, CollectionSearch, Notifiable, Delegatabl
79
79
  loop_control = NonInheritableFieldAttribute(isa='class', class_type=LoopControl, default=LoopControl)
80
80
  poll = NonInheritableFieldAttribute(isa='int', default=C.DEFAULT_POLL_INTERVAL)
81
81
  register = NonInheritableFieldAttribute(isa='string', static=True)
82
- retries = NonInheritableFieldAttribute(isa='int', default=3)
82
+ retries = NonInheritableFieldAttribute(isa='int') # default is set in TaskExecutor
83
83
  until = NonInheritableFieldAttribute(isa='list', default=list)
84
84
 
85
85
  # deprecated, used to be loop and loop_args but loop has been repurposed
@@ -35,7 +35,7 @@ class TaskInclude(Task):
35
35
 
36
36
  """
37
37
  A task include is derived from a regular task to handle the special
38
- circumstances related to the `- include: ...` task.
38
+ circumstances related to the `- include_*: ...` task.
39
39
  """
40
40
 
41
41
  BASE = frozenset(('file', '_raw_params')) # directly assigned
@@ -105,29 +105,6 @@ class TaskInclude(Task):
105
105
  new_me.statically_loaded = self.statically_loaded
106
106
  return new_me
107
107
 
108
- def get_vars(self):
109
- '''
110
- We override the parent Task() classes get_vars here because
111
- we need to include the args of the include into the vars as
112
- they are params to the included tasks. But ONLY for 'include'
113
- '''
114
- if self.action not in C._ACTION_INCLUDE:
115
- all_vars = super(TaskInclude, self).get_vars()
116
- else:
117
- all_vars = dict()
118
- if self._parent:
119
- all_vars |= self._parent.get_vars()
120
-
121
- all_vars |= self.vars
122
- all_vars |= self.args
123
-
124
- if 'tags' in all_vars:
125
- del all_vars['tags']
126
- if 'when' in all_vars:
127
- del all_vars['when']
128
-
129
- return all_vars
130
-
131
108
  def build_parent_block(self):
132
109
  '''
133
110
  This method is used to create the parent block for the included tasks
@@ -28,7 +28,7 @@ import typing as t
28
28
 
29
29
  from ansible import constants as C
30
30
  from ansible.errors import AnsibleError
31
- from ansible.module_utils._text import to_native
31
+ from ansible.module_utils.common.text.converters import to_native
32
32
  from ansible.module_utils.six import string_types
33
33
  from ansible.utils.display import Display
34
34
 
@@ -55,6 +55,9 @@ class AnsiblePlugin(ABC):
55
55
  # allow extra passthrough parameters
56
56
  allow_extras = False
57
57
 
58
+ # Set by plugin loader
59
+ _load_name: str
60
+
58
61
  def __init__(self):
59
62
  self._options = {}
60
63
  self._defs = None
@@ -69,12 +72,17 @@ class AnsiblePlugin(ABC):
69
72
  possible_fqcns.add(name)
70
73
  return bool(possible_fqcns.intersection(set(self.ansible_aliases)))
71
74
 
75
+ def get_option_and_origin(self, option, hostvars=None):
76
+ try:
77
+ option_value, origin = C.config.get_config_value_and_origin(option, plugin_type=self.plugin_type, plugin_name=self._load_name, variables=hostvars)
78
+ except AnsibleError as e:
79
+ raise KeyError(to_native(e))
80
+ return option_value, origin
81
+
72
82
  def get_option(self, option, hostvars=None):
83
+
73
84
  if option not in self._options:
74
- try:
75
- option_value = C.config.get_config_value(option, plugin_type=self.plugin_type, plugin_name=self._load_name, variables=hostvars)
76
- except AnsibleError as e:
77
- raise KeyError(to_native(e))
85
+ option_value, dummy = self.get_option_and_origin(option, hostvars=hostvars)
78
86
  self.set_option(option, option_value)
79
87
  return self._options.get(option)
80
88
 
@@ -27,7 +27,7 @@ from ansible.module_utils.common.arg_spec import ArgumentSpecValidator
27
27
  from ansible.module_utils.errors import UnsupportedError
28
28
  from ansible.module_utils.json_utils import _filter_non_json_lines
29
29
  from ansible.module_utils.six import binary_type, string_types, text_type
30
- from ansible.module_utils._text import to_bytes, to_native, to_text
30
+ from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text
31
31
  from ansible.parsing.utils.jsonify import jsonify
32
32
  from ansible.release import __version__
33
33
  from ansible.utils.collection_loader import resource_from_fqcr
@@ -63,6 +63,13 @@ class ActionBase(ABC):
63
63
  # A set of valid arguments
64
64
  _VALID_ARGS = frozenset([]) # type: frozenset[str]
65
65
 
66
+ # behavioral attributes
67
+ BYPASS_HOST_LOOP = False
68
+ TRANSFERS_FILES = False
69
+ _requires_connection = True
70
+ _supports_check_mode = True
71
+ _supports_async = False
72
+
66
73
  def __init__(self, task, connection, play_context, loader, templar, shared_loader_obj):
67
74
  self._task = task
68
75
  self._connection = connection
@@ -72,20 +79,16 @@ class ActionBase(ABC):
72
79
  self._shared_loader_obj = shared_loader_obj
73
80
  self._cleanup_remote_tmp = False
74
81
 
75
- self._supports_check_mode = True
76
- self._supports_async = False
77
-
78
82
  # interpreter discovery state
79
83
  self._discovered_interpreter_key = None
80
84
  self._discovered_interpreter = False
81
85
  self._discovery_deprecation_warnings = []
82
86
  self._discovery_warnings = []
87
+ self._used_interpreter = None
83
88
 
84
89
  # Backwards compat: self._display isn't really needed, just import the global display and use that.
85
90
  self._display = display
86
91
 
87
- self._used_interpreter = None
88
-
89
92
  @abstractmethod
90
93
  def run(self, tmp=None, task_vars=None):
91
94
  """ Action Plugins should implement this method to perform their
@@ -296,7 +299,8 @@ class ActionBase(ABC):
296
299
  try:
297
300
  (module_data, module_style, module_shebang) = modify_module(module_name, module_path, module_args, self._templar,
298
301
  task_vars=use_vars,
299
- module_compression=self._play_context.module_compression,
302
+ module_compression=C.config.get_config_value('DEFAULT_MODULE_COMPRESSION',
303
+ variables=task_vars),
300
304
  async_timeout=self._task.async_val,
301
305
  environment=final_environment,
302
306
  remote_is_local=bool(getattr(self._connection, '_remote_is_local', False)),
@@ -735,8 +739,7 @@ class ActionBase(ABC):
735
739
  return remote_paths
736
740
 
737
741
  # we'll need this down here
738
- become_link = get_versioned_doclink('playbook_guide/playbooks_privilege_escalation.html#risks-of-becoming-an-unprivileged-user')
739
-
742
+ become_link = get_versioned_doclink('playbook_guide/playbooks_privilege_escalation.html')
740
743
  # Step 3f: Common group
741
744
  # Otherwise, we're a normal user. We failed to chown the paths to the
742
745
  # unprivileged user, but if we have a common group with them, we should
@@ -873,38 +876,6 @@ class ActionBase(ABC):
873
876
 
874
877
  return mystat['stat']
875
878
 
876
- def _remote_checksum(self, path, all_vars, follow=False):
877
- """Deprecated. Use _execute_remote_stat() instead.
878
-
879
- Produces a remote checksum given a path,
880
- Returns a number 0-4 for specific errors instead of checksum, also ensures it is different
881
- 0 = unknown error
882
- 1 = file does not exist, this might not be an error
883
- 2 = permissions issue
884
- 3 = its a directory, not a file
885
- 4 = stat module failed, likely due to not finding python
886
- 5 = appropriate json module not found
887
- """
888
- self._display.deprecated("The '_remote_checksum()' method is deprecated. "
889
- "The plugin author should update the code to use '_execute_remote_stat()' instead", "2.16")
890
- x = "0" # unknown error has occurred
891
- try:
892
- remote_stat = self._execute_remote_stat(path, all_vars, follow=follow)
893
- if remote_stat['exists'] and remote_stat['isdir']:
894
- x = "3" # its a directory not a file
895
- else:
896
- x = remote_stat['checksum'] # if 1, file is missing
897
- except AnsibleError as e:
898
- errormsg = to_text(e)
899
- if errormsg.endswith(u'Permission denied'):
900
- x = "2" # cannot read file
901
- elif errormsg.endswith(u'MODULE FAILURE'):
902
- x = "4" # python not found or module uncaught exception
903
- elif 'json' in errormsg:
904
- x = "5" # json module needed
905
- finally:
906
- return x # pylint: disable=lost-exception
907
-
908
879
  def _remote_expand_user(self, path, sudoable=True, pathsep=None):
909
880
  ''' takes a remote path and performs tilde/$HOME expansion on the remote host '''
910
881
 
@@ -1368,7 +1339,7 @@ class ActionBase(ABC):
1368
1339
  display.debug(u"_low_level_execute_command() done: rc=%d, stdout=%s, stderr=%s" % (rc, out, err))
1369
1340
  return dict(rc=rc, stdout=out, stdout_lines=out.splitlines(), stderr=err, stderr_lines=err.splitlines())
1370
1341
 
1371
- def _get_diff_data(self, destination, source, task_vars, source_file=True):
1342
+ def _get_diff_data(self, destination, source, task_vars, content, source_file=True):
1372
1343
 
1373
1344
  # Note: Since we do not diff the source and destination before we transform from bytes into
1374
1345
  # text the diff between source and destination may not be accurate. To fix this, we'd need
@@ -1426,7 +1397,10 @@ class ActionBase(ABC):
1426
1397
  if b"\x00" in src_contents:
1427
1398
  diff['src_binary'] = 1
1428
1399
  else:
1429
- diff['after_header'] = source
1400
+ if content:
1401
+ diff['after_header'] = destination
1402
+ else:
1403
+ diff['after_header'] = source
1430
1404
  diff['after'] = to_text(src_contents)
1431
1405
  else:
1432
1406
  display.debug(u"source of file passed in")
@@ -37,12 +37,11 @@ class ActionModule(ActionBase):
37
37
 
38
38
  # We need to be able to modify the inventory
39
39
  BYPASS_HOST_LOOP = True
40
- TRANSFERS_FILES = False
40
+ _requires_connection = False
41
+ _supports_check_mode = True
41
42
 
42
43
  def run(self, tmp=None, task_vars=None):
43
44
 
44
- self._supports_check_mode = True
45
-
46
45
  result = super(ActionModule, self).run(tmp, task_vars)
47
46
  del tmp # tmp no longer has any effect
48
47
 
@@ -27,7 +27,7 @@ import tempfile
27
27
 
28
28
  from ansible import constants as C
29
29
  from ansible.errors import AnsibleError, AnsibleAction, _AnsibleActionDone, AnsibleActionFail
30
- from ansible.module_utils._text import to_native, to_text
30
+ from ansible.module_utils.common.text.converters import to_native, to_text
31
31
  from ansible.module_utils.parsing.convert_bool import boolean
32
32
  from ansible.plugins.action import ActionBase
33
33
  from ansible.utils.hashing import checksum_s
@@ -27,7 +27,8 @@ from ansible.module_utils.parsing.convert_bool import boolean
27
27
  class ActionModule(ActionBase):
28
28
  ''' Fail with custom message '''
29
29
 
30
- TRANSFERS_FILES = False
30
+ _requires_connection = False
31
+
31
32
  _VALID_ARGS = frozenset(('fail_msg', 'msg', 'quiet', 'success_msg', 'that'))
32
33
 
33
34
  def run(self, tmp=None, task_vars=None):
@@ -30,7 +30,7 @@ import traceback
30
30
  from ansible import constants as C
31
31
  from ansible.errors import AnsibleError, AnsibleFileNotFound
32
32
  from ansible.module_utils.basic import FILE_COMMON_ARGUMENTS
33
- from ansible.module_utils._text import to_bytes, to_native, to_text
33
+ from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text
34
34
  from ansible.module_utils.parsing.convert_bool import boolean
35
35
  from ansible.plugins.action import ActionBase
36
36
  from ansible.utils.hashing import checksum
@@ -286,7 +286,7 @@ class ActionModule(ActionBase):
286
286
  # The checksums don't match and we will change or error out.
287
287
 
288
288
  if self._play_context.diff and not raw:
289
- result['diff'].append(self._get_diff_data(dest_file, source_full, task_vars))
289
+ result['diff'].append(self._get_diff_data(dest_file, source_full, task_vars, content))
290
290
 
291
291
  if self._play_context.check_mode:
292
292
  self._remove_tempfile_if_content_defined(content, content_tempfile)
@@ -20,7 +20,7 @@ __metaclass__ = type
20
20
 
21
21
  from ansible.errors import AnsibleUndefinedVariable
22
22
  from ansible.module_utils.six import string_types
23
- from ansible.module_utils._text import to_text
23
+ from ansible.module_utils.common.text.converters import to_text
24
24
  from ansible.plugins.action import ActionBase
25
25
 
26
26
 
@@ -29,6 +29,7 @@ class ActionModule(ActionBase):
29
29
 
30
30
  TRANSFERS_FILES = False
31
31
  _VALID_ARGS = frozenset(('msg', 'var', 'verbosity'))
32
+ _requires_connection = False
32
33
 
33
34
  def run(self, tmp=None, task_vars=None):
34
35
  if task_vars is None:
@@ -26,6 +26,7 @@ class ActionModule(ActionBase):
26
26
 
27
27
  TRANSFERS_FILES = False
28
28
  _VALID_ARGS = frozenset(('msg',))
29
+ _requires_connection = False
29
30
 
30
31
  def run(self, tmp=None, task_vars=None):
31
32
  if task_vars is None:
@@ -19,7 +19,7 @@ __metaclass__ = type
19
19
 
20
20
  import os
21
21
  import base64
22
- from ansible.errors import AnsibleError, AnsibleActionFail, AnsibleActionSkip
22
+ from ansible.errors import AnsibleConnectionFailure, AnsibleError, AnsibleActionFail, AnsibleActionSkip
23
23
  from ansible.module_utils.common.text.converters import to_bytes, to_text
24
24
  from ansible.module_utils.six import string_types
25
25
  from ansible.module_utils.parsing.convert_bool import boolean
@@ -75,6 +75,8 @@ class ActionModule(ActionBase):
75
75
  # Follow symlinks because fetch always follows symlinks
76
76
  try:
77
77
  remote_stat = self._execute_remote_stat(source, all_vars=task_vars, follow=True)
78
+ except AnsibleConnectionFailure:
79
+ raise
78
80
  except AnsibleError as ae:
79
81
  result['changed'] = False
80
82
  result['file'] = source
@@ -6,6 +6,7 @@ __metaclass__ = type
6
6
 
7
7
  import os
8
8
  import time
9
+ import typing as t
9
10
 
10
11
  from ansible import constants as C
11
12
  from ansible.executor.module_common import get_action_args_with_defaults
@@ -16,12 +17,15 @@ from ansible.utils.vars import merge_hash
16
17
 
17
18
  class ActionModule(ActionBase):
18
19
 
19
- def _get_module_args(self, fact_module, task_vars):
20
+ _supports_check_mode = True
21
+
22
+ def _get_module_args(self, fact_module: str, task_vars: dict[str, t.Any]) -> dict[str, t.Any]:
20
23
 
21
24
  mod_args = self._task.args.copy()
22
25
 
23
26
  # deal with 'setup specific arguments'
24
27
  if fact_module not in C._ACTION_SETUP:
28
+
25
29
  # TODO: remove in favor of controller side argspec detecing valid arguments
26
30
  # network facts modules must support gather_subset
27
31
  try:
@@ -30,16 +34,16 @@ class ActionModule(ActionBase):
30
34
  name = self._connection._load_name.split('.')[-1]
31
35
  if name not in ('network_cli', 'httpapi', 'netconf'):
32
36
  subset = mod_args.pop('gather_subset', None)
33
- if subset not in ('all', ['all']):
34
- self._display.warning('Ignoring subset(%s) for %s' % (subset, fact_module))
37
+ if subset not in ('all', ['all'], None):
38
+ self._display.warning('Not passing subset(%s) to %s' % (subset, fact_module))
35
39
 
36
40
  timeout = mod_args.pop('gather_timeout', None)
37
41
  if timeout is not None:
38
- self._display.warning('Ignoring timeout(%s) for %s' % (timeout, fact_module))
42
+ self._display.warning('Not passing timeout(%s) to %s' % (timeout, fact_module))
39
43
 
40
44
  fact_filter = mod_args.pop('filter', None)
41
45
  if fact_filter is not None:
42
- self._display.warning('Ignoring filter(%s) for %s' % (fact_filter, fact_module))
46
+ self._display.warning('Not passing filter(%s) to %s' % (fact_filter, fact_module))
43
47
 
44
48
  # Strip out keys with ``None`` values, effectively mimicking ``omit`` behavior
45
49
  # This ensures we don't pass a ``None`` value as an argument expecting a specific type
@@ -57,7 +61,7 @@ class ActionModule(ActionBase):
57
61
 
58
62
  return mod_args
59
63
 
60
- def _combine_task_result(self, result, task_result):
64
+ def _combine_task_result(self, result: dict[str, t.Any], task_result: dict[str, t.Any]) -> dict[str, t.Any]:
61
65
  filtered_res = {
62
66
  'ansible_facts': task_result.get('ansible_facts', {}),
63
67
  'warnings': task_result.get('warnings', []),
@@ -67,9 +71,7 @@ class ActionModule(ActionBase):
67
71
  # on conflict the last plugin processed wins, but try to do deep merge and append to lists.
68
72
  return merge_hash(result, filtered_res, list_merge='append_rp')
69
73
 
70
- def run(self, tmp=None, task_vars=None):
71
-
72
- self._supports_check_mode = True
74
+ def run(self, tmp: t.Optional[str] = None, task_vars: t.Optional[dict[str, t.Any]] = None) -> dict[str, t.Any]:
73
75
 
74
76
  result = super(ActionModule, self).run(tmp, task_vars)
75
77
  result['ansible_facts'] = {}
@@ -87,16 +89,23 @@ class ActionModule(ActionBase):
87
89
  failed = {}
88
90
  skipped = {}
89
91
 
90
- if parallel is None and len(modules) >= 1:
91
- parallel = True
92
+ if parallel is None:
93
+ if len(modules) > 1:
94
+ parallel = True
95
+ else:
96
+ parallel = False
92
97
  else:
93
98
  parallel = boolean(parallel)
94
99
 
95
- if parallel:
100
+ timeout = self._task.args.get('gather_timeout', None)
101
+ async_val = self._task.async_val
102
+
103
+ if not parallel:
96
104
  # serially execute each module
97
105
  for fact_module in modules:
98
106
  # just one module, no need for fancy async
99
107
  mod_args = self._get_module_args(fact_module, task_vars)
108
+ # TODO: use gather_timeout to cut module execution if module itself does not support gather_timeout
100
109
  res = self._execute_module(module_name=fact_module, module_args=mod_args, task_vars=task_vars, wrap_async=False)
101
110
  if res.get('failed', False):
102
111
  failed[fact_module] = res
@@ -107,10 +116,21 @@ class ActionModule(ActionBase):
107
116
 
108
117
  self._remove_tmp_path(self._connection._shell.tmpdir)
109
118
  else:
110
- # do it async
119
+ # do it async, aka parallel
111
120
  jobs = {}
121
+
112
122
  for fact_module in modules:
113
123
  mod_args = self._get_module_args(fact_module, task_vars)
124
+
125
+ # if module does not handle timeout, use timeout to handle module, hijack async_val as this is what async_wrapper uses
126
+ # TODO: make this action compain about async/async settings, use parallel option instead .. or remove parallel in favor of async settings?
127
+ if timeout and 'gather_timeout' not in mod_args:
128
+ self._task.async_val = int(timeout)
129
+ elif async_val != 0:
130
+ self._task.async_val = async_val
131
+ else:
132
+ self._task.async_val = 0
133
+
114
134
  self._display.vvvv("Running %s" % fact_module)
115
135
  jobs[fact_module] = (self._execute_module(module_name=fact_module, module_args=mod_args, task_vars=task_vars, wrap_async=True))
116
136
 
@@ -132,6 +152,10 @@ class ActionModule(ActionBase):
132
152
  else:
133
153
  time.sleep(0.5)
134
154
 
155
+ # restore value for post processing
156
+ if self._task.async_val != async_val:
157
+ self._task.async_val = async_val
158
+
135
159
  if skipped:
136
160
  result['msg'] = "The following modules were skipped: %s\n" % (', '.join(skipped.keys()))
137
161
  result['skipped_modules'] = skipped