ansible-core 2.16.5__py3-none-any.whl → 2.17.0b1__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 (597) hide show
  1. ansible/__init__.py +1 -3
  2. ansible/__main__.py +1 -0
  3. ansible/_vendor/__init__.py +1 -2
  4. ansible/cli/__init__.py +7 -8
  5. ansible/cli/adhoc.py +1 -2
  6. ansible/cli/arguments/__init__.py +1 -2
  7. ansible/cli/arguments/option_helpers.py +1 -2
  8. ansible/cli/config.py +1 -2
  9. ansible/cli/console.py +1 -2
  10. ansible/cli/doc.py +320 -198
  11. ansible/cli/galaxy.py +9 -3
  12. ansible/cli/inventory.py +5 -27
  13. ansible/cli/playbook.py +1 -2
  14. ansible/cli/pull.py +4 -5
  15. ansible/cli/scripts/ansible_connection_cli_stub.py +1 -4
  16. ansible/cli/vault.py +1 -2
  17. ansible/collections/list.py +1 -0
  18. ansible/compat/__init__.py +1 -4
  19. ansible/compat/importlib_resources.py +1 -2
  20. ansible/compat/{selectors/__init__.py → selectors.py} +12 -12
  21. ansible/config/ansible_builtin_runtime.yml +2 -0
  22. ansible/config/base.yml +154 -149
  23. ansible/config/manager.py +32 -25
  24. ansible/constants.py +41 -2
  25. ansible/context.py +1 -4
  26. ansible/errors/__init__.py +1 -3
  27. ansible/errors/yaml_strings.py +1 -3
  28. ansible/executor/__init__.py +1 -3
  29. ansible/executor/discovery/python_target.py +1 -2
  30. ansible/executor/interpreter_discovery.py +9 -8
  31. ansible/executor/module_common.py +1 -3
  32. ansible/executor/play_iterator.py +1 -3
  33. ansible/executor/playbook_executor.py +1 -3
  34. ansible/executor/powershell/module_manifest.py +2 -3
  35. ansible/executor/process/__init__.py +1 -3
  36. ansible/executor/process/worker.py +1 -3
  37. ansible/executor/stats.py +1 -3
  38. ansible/executor/task_executor.py +10 -5
  39. ansible/executor/task_queue_manager.py +1 -3
  40. ansible/executor/task_result.py +2 -3
  41. ansible/galaxy/__init__.py +1 -2
  42. ansible/galaxy/api.py +10 -2
  43. ansible/galaxy/collection/__init__.py +38 -24
  44. ansible/galaxy/collection/concrete_artifact_manager.py +1 -2
  45. ansible/galaxy/collection/galaxy_api_proxy.py +1 -2
  46. ansible/galaxy/collection/gpg.py +4 -2
  47. ansible/galaxy/data/apb/meta/main.yml.j2 +0 -15
  48. ansible/galaxy/data/container/meta/main.yml.j2 +0 -18
  49. ansible/galaxy/data/default/role/meta/main.yml.j2 +0 -18
  50. ansible/galaxy/data/network/cliconf_plugins/example.py.j2 +1 -2
  51. ansible/galaxy/data/network/library/example_command.py.j2 +1 -2
  52. ansible/galaxy/data/network/library/example_config.py.j2 +1 -2
  53. ansible/galaxy/data/network/library/example_facts.py.j2 +1 -2
  54. ansible/galaxy/data/network/meta/main.yml.j2 +0 -15
  55. ansible/galaxy/data/network/module_utils/example.py.j2 +1 -2
  56. ansible/galaxy/data/network/netconf_plugins/example.py.j2 +1 -2
  57. ansible/galaxy/data/network/terminal_plugins/example.py.j2 +1 -2
  58. ansible/galaxy/dependency_resolution/__init__.py +1 -2
  59. ansible/galaxy/dependency_resolution/dataclasses.py +5 -6
  60. ansible/galaxy/dependency_resolution/errors.py +1 -2
  61. ansible/galaxy/dependency_resolution/providers.py +3 -4
  62. ansible/galaxy/dependency_resolution/reporters.py +2 -3
  63. ansible/galaxy/dependency_resolution/resolvers.py +1 -2
  64. ansible/galaxy/dependency_resolution/versioning.py +1 -2
  65. ansible/galaxy/role.py +2 -3
  66. ansible/galaxy/token.py +1 -2
  67. ansible/galaxy/user_agent.py +1 -2
  68. ansible/inventory/data.py +1 -2
  69. ansible/inventory/group.py +1 -2
  70. ansible/inventory/helpers.py +1 -2
  71. ansible/inventory/host.py +1 -3
  72. ansible/inventory/manager.py +1 -2
  73. ansible/module_utils/_text.py +1 -2
  74. ansible/module_utils/ansible_release.py +3 -5
  75. ansible/module_utils/api.py +1 -2
  76. ansible/module_utils/basic.py +113 -158
  77. ansible/module_utils/common/_collections_compat.py +1 -2
  78. ansible/module_utils/common/_utils.py +1 -3
  79. ansible/module_utils/common/arg_spec.py +1 -2
  80. ansible/module_utils/common/collections.py +1 -2
  81. ansible/module_utils/common/dict_transformations.py +1 -2
  82. ansible/module_utils/common/file.py +10 -5
  83. ansible/module_utils/common/json.py +1 -3
  84. ansible/module_utils/common/locale.py +1 -2
  85. ansible/module_utils/common/network.py +2 -3
  86. ansible/module_utils/common/parameters.py +9 -9
  87. ansible/module_utils/common/process.py +12 -5
  88. ansible/module_utils/common/respawn.py +2 -3
  89. ansible/module_utils/common/sys_info.py +1 -2
  90. ansible/module_utils/common/text/converters.py +1 -2
  91. ansible/module_utils/common/text/formatters.py +1 -2
  92. ansible/module_utils/common/validation.py +5 -6
  93. ansible/module_utils/common/warnings.py +1 -2
  94. ansible/module_utils/common/yaml.py +1 -2
  95. ansible/module_utils/compat/datetime.py +1 -3
  96. ansible/module_utils/compat/importlib.py +21 -13
  97. ansible/module_utils/compat/paramiko.py +1 -2
  98. ansible/module_utils/compat/selectors.py +10 -34
  99. ansible/module_utils/compat/selinux.py +1 -2
  100. ansible/module_utils/compat/typing.py +1 -2
  101. ansible/module_utils/compat/version.py +1 -2
  102. ansible/module_utils/connection.py +1 -2
  103. ansible/module_utils/csharp/Ansible.Basic.cs +20 -3
  104. ansible/module_utils/distro/__init__.py +2 -3
  105. ansible/module_utils/distro/_distro.py +230 -234
  106. ansible/module_utils/errors.py +1 -2
  107. ansible/module_utils/facts/__init__.py +1 -2
  108. ansible/module_utils/facts/ansible_collector.py +1 -2
  109. ansible/module_utils/facts/collector.py +1 -2
  110. ansible/module_utils/facts/compat.py +1 -2
  111. ansible/module_utils/facts/default_collectors.py +1 -2
  112. ansible/module_utils/facts/hardware/aix.py +1 -2
  113. ansible/module_utils/facts/hardware/base.py +1 -2
  114. ansible/module_utils/facts/hardware/darwin.py +1 -2
  115. ansible/module_utils/facts/hardware/dragonfly.py +1 -2
  116. ansible/module_utils/facts/hardware/freebsd.py +1 -2
  117. ansible/module_utils/facts/hardware/hpux.py +1 -2
  118. ansible/module_utils/facts/hardware/hurd.py +1 -2
  119. ansible/module_utils/facts/hardware/linux.py +8 -6
  120. ansible/module_utils/facts/hardware/netbsd.py +1 -2
  121. ansible/module_utils/facts/hardware/openbsd.py +1 -2
  122. ansible/module_utils/facts/hardware/sunos.py +2 -3
  123. ansible/module_utils/facts/namespace.py +1 -2
  124. ansible/module_utils/facts/network/aix.py +1 -2
  125. ansible/module_utils/facts/network/base.py +1 -2
  126. ansible/module_utils/facts/network/darwin.py +1 -2
  127. ansible/module_utils/facts/network/dragonfly.py +1 -2
  128. ansible/module_utils/facts/network/fc_wwn.py +1 -2
  129. ansible/module_utils/facts/network/freebsd.py +1 -2
  130. ansible/module_utils/facts/network/generic_bsd.py +1 -2
  131. ansible/module_utils/facts/network/hpux.py +1 -2
  132. ansible/module_utils/facts/network/hurd.py +1 -2
  133. ansible/module_utils/facts/network/iscsi.py +1 -2
  134. ansible/module_utils/facts/network/linux.py +1 -2
  135. ansible/module_utils/facts/network/netbsd.py +1 -2
  136. ansible/module_utils/facts/network/nvme.py +1 -2
  137. ansible/module_utils/facts/network/openbsd.py +1 -2
  138. ansible/module_utils/facts/network/sunos.py +1 -2
  139. ansible/module_utils/facts/other/facter.py +1 -2
  140. ansible/module_utils/facts/other/ohai.py +1 -2
  141. ansible/module_utils/facts/packages.py +1 -2
  142. ansible/module_utils/facts/sysctl.py +1 -2
  143. ansible/module_utils/facts/system/apparmor.py +1 -2
  144. ansible/module_utils/facts/system/caps.py +1 -2
  145. ansible/module_utils/facts/system/chroot.py +1 -2
  146. ansible/module_utils/facts/system/cmdline.py +1 -2
  147. ansible/module_utils/facts/system/date_time.py +1 -2
  148. ansible/module_utils/facts/system/distribution.py +4 -5
  149. ansible/module_utils/facts/system/dns.py +1 -2
  150. ansible/module_utils/facts/system/env.py +1 -2
  151. ansible/module_utils/facts/system/fips.py +1 -2
  152. ansible/module_utils/facts/system/loadavg.py +1 -2
  153. ansible/module_utils/facts/system/local.py +1 -2
  154. ansible/module_utils/facts/system/lsb.py +1 -2
  155. ansible/module_utils/facts/system/pkg_mgr.py +7 -30
  156. ansible/module_utils/facts/system/platform.py +1 -2
  157. ansible/module_utils/facts/system/python.py +1 -2
  158. ansible/module_utils/facts/system/selinux.py +1 -2
  159. ansible/module_utils/facts/system/service_mgr.py +1 -2
  160. ansible/module_utils/facts/system/ssh_pub_keys.py +1 -2
  161. ansible/module_utils/facts/system/user.py +1 -2
  162. ansible/module_utils/facts/timeout.py +1 -2
  163. ansible/module_utils/facts/utils.py +1 -2
  164. ansible/module_utils/facts/virtual/base.py +1 -2
  165. ansible/module_utils/facts/virtual/dragonfly.py +1 -2
  166. ansible/module_utils/facts/virtual/freebsd.py +1 -2
  167. ansible/module_utils/facts/virtual/hpux.py +1 -2
  168. ansible/module_utils/facts/virtual/linux.py +2 -3
  169. ansible/module_utils/facts/virtual/netbsd.py +1 -2
  170. ansible/module_utils/facts/virtual/openbsd.py +1 -2
  171. ansible/module_utils/facts/virtual/sunos.py +1 -2
  172. ansible/module_utils/facts/virtual/sysctl.py +1 -2
  173. ansible/module_utils/json_utils.py +1 -2
  174. ansible/module_utils/parsing/convert_bool.py +1 -2
  175. ansible/module_utils/powershell/Ansible.ModuleUtils.Legacy.psm1 +5 -2
  176. ansible/module_utils/powershell/Ansible.ModuleUtils.WebRequest.psm1 +1 -1
  177. ansible/module_utils/pycompat24.py +24 -4
  178. ansible/module_utils/service.py +31 -5
  179. ansible/module_utils/six/__init__.py +1 -1
  180. ansible/module_utils/splitter.py +1 -2
  181. ansible/module_utils/urls.py +335 -1052
  182. ansible/module_utils/yumdnf.py +13 -35
  183. ansible/modules/add_host.py +1 -2
  184. ansible/modules/apt.py +38 -22
  185. ansible/modules/apt_key.py +1 -2
  186. ansible/modules/apt_repository.py +18 -10
  187. ansible/modules/assemble.py +1 -2
  188. ansible/modules/assert.py +8 -4
  189. ansible/modules/async_status.py +17 -14
  190. ansible/modules/async_wrapper.py +11 -9
  191. ansible/modules/blockinfile.py +3 -4
  192. ansible/modules/command.py +1 -2
  193. ansible/modules/copy.py +4 -76
  194. ansible/modules/cron.py +3 -3
  195. ansible/modules/deb822_repository.py +5 -5
  196. ansible/modules/debconf.py +19 -8
  197. ansible/modules/debug.py +1 -2
  198. ansible/modules/dnf.py +63 -188
  199. ansible/modules/dnf5.py +57 -43
  200. ansible/modules/dpkg_selections.py +1 -2
  201. ansible/modules/expect.py +23 -15
  202. ansible/modules/fail.py +1 -2
  203. ansible/modules/fetch.py +1 -2
  204. ansible/modules/file.py +4 -3
  205. ansible/modules/find.py +25 -9
  206. ansible/modules/gather_facts.py +1 -2
  207. ansible/modules/get_url.py +2 -3
  208. ansible/modules/getent.py +2 -3
  209. ansible/modules/git.py +28 -17
  210. ansible/modules/group.py +1 -2
  211. ansible/modules/group_by.py +1 -2
  212. ansible/modules/hostname.py +2 -19
  213. ansible/modules/import_playbook.py +1 -2
  214. ansible/modules/import_role.py +9 -2
  215. ansible/modules/import_tasks.py +1 -2
  216. ansible/modules/include_role.py +1 -2
  217. ansible/modules/include_tasks.py +1 -2
  218. ansible/modules/include_vars.py +1 -2
  219. ansible/modules/iptables.py +38 -21
  220. ansible/modules/known_hosts.py +15 -8
  221. ansible/modules/lineinfile.py +1 -6
  222. ansible/modules/meta.py +3 -2
  223. ansible/modules/package.py +6 -5
  224. ansible/modules/package_facts.py +1 -2
  225. ansible/modules/pause.py +2 -3
  226. ansible/modules/ping.py +1 -2
  227. ansible/modules/pip.py +40 -20
  228. ansible/modules/raw.py +1 -2
  229. ansible/modules/reboot.py +1 -2
  230. ansible/modules/replace.py +7 -5
  231. ansible/modules/rpm_key.py +1 -2
  232. ansible/modules/script.py +1 -2
  233. ansible/modules/service.py +3 -21
  234. ansible/modules/service_facts.py +3 -12
  235. ansible/modules/set_fact.py +1 -2
  236. ansible/modules/set_stats.py +1 -2
  237. ansible/modules/setup.py +1 -2
  238. ansible/modules/shell.py +1 -2
  239. ansible/modules/slurp.py +1 -2
  240. ansible/modules/stat.py +1 -2
  241. ansible/modules/subversion.py +2 -3
  242. ansible/modules/systemd.py +12 -9
  243. ansible/modules/systemd_service.py +12 -9
  244. ansible/modules/sysvinit.py +7 -2
  245. ansible/modules/tempfile.py +7 -2
  246. ansible/modules/template.py +2 -3
  247. ansible/modules/unarchive.py +14 -4
  248. ansible/modules/uri.py +5 -8
  249. ansible/modules/user.py +11 -10
  250. ansible/modules/validate_argument_spec.py +15 -16
  251. ansible/modules/wait_for.py +1 -2
  252. ansible/modules/wait_for_connection.py +1 -2
  253. ansible/modules/yum_repository.py +2 -3
  254. ansible/parsing/__init__.py +1 -3
  255. ansible/parsing/ajson.py +1 -3
  256. ansible/parsing/dataloader.py +23 -12
  257. ansible/parsing/mod_args.py +14 -8
  258. ansible/parsing/plugin_docs.py +1 -2
  259. ansible/parsing/quoting.py +1 -3
  260. ansible/parsing/splitter.py +1 -3
  261. ansible/parsing/utils/__init__.py +1 -3
  262. ansible/parsing/utils/addresses.py +1 -3
  263. ansible/parsing/utils/jsonify.py +1 -3
  264. ansible/parsing/utils/yaml.py +1 -3
  265. ansible/parsing/vault/__init__.py +6 -8
  266. ansible/parsing/yaml/__init__.py +1 -3
  267. ansible/parsing/yaml/constructor.py +1 -3
  268. ansible/parsing/yaml/dumper.py +1 -3
  269. ansible/parsing/yaml/loader.py +1 -3
  270. ansible/parsing/yaml/objects.py +1 -3
  271. ansible/playbook/__init__.py +1 -3
  272. ansible/playbook/attribute.py +1 -3
  273. ansible/playbook/base.py +2 -3
  274. ansible/playbook/block.py +1 -3
  275. ansible/playbook/collectionsearch.py +1 -2
  276. ansible/playbook/conditional.py +1 -3
  277. ansible/playbook/delegatable.py +1 -0
  278. ansible/playbook/handler.py +2 -4
  279. ansible/playbook/handler_task_include.py +1 -3
  280. ansible/playbook/helpers.py +1 -4
  281. ansible/playbook/included_file.py +4 -4
  282. ansible/playbook/loop_control.py +1 -3
  283. ansible/playbook/notifiable.py +1 -0
  284. ansible/playbook/play.py +1 -3
  285. ansible/playbook/play_context.py +1 -3
  286. ansible/playbook/playbook_include.py +1 -3
  287. ansible/playbook/role/__init__.py +2 -4
  288. ansible/playbook/role/definition.py +1 -3
  289. ansible/playbook/role/include.py +1 -3
  290. ansible/playbook/role/metadata.py +1 -3
  291. ansible/playbook/role/requirement.py +1 -3
  292. ansible/playbook/role_include.py +2 -10
  293. ansible/playbook/taggable.py +1 -3
  294. ansible/playbook/task.py +2 -4
  295. ansible/playbook/task_include.py +1 -3
  296. ansible/plugins/__init__.py +4 -5
  297. ansible/plugins/action/__init__.py +20 -14
  298. ansible/plugins/action/add_host.py +2 -4
  299. ansible/plugins/action/assemble.py +2 -3
  300. ansible/plugins/action/assert.py +1 -2
  301. ansible/plugins/action/async_status.py +1 -2
  302. ansible/plugins/action/command.py +1 -2
  303. ansible/plugins/action/copy.py +12 -9
  304. ansible/plugins/action/debug.py +1 -2
  305. ansible/plugins/action/dnf.py +4 -4
  306. ansible/plugins/action/fail.py +1 -2
  307. ansible/plugins/action/fetch.py +6 -3
  308. ansible/plugins/action/gather_facts.py +3 -4
  309. ansible/plugins/action/group_by.py +1 -2
  310. ansible/plugins/action/include_vars.py +1 -2
  311. ansible/plugins/action/normal.py +1 -2
  312. ansible/plugins/action/package.py +36 -21
  313. ansible/plugins/action/pause.py +1 -2
  314. ansible/plugins/action/raw.py +2 -3
  315. ansible/plugins/action/reboot.py +30 -15
  316. ansible/plugins/action/script.py +3 -4
  317. ansible/plugins/action/service.py +1 -2
  318. ansible/plugins/action/set_fact.py +1 -2
  319. ansible/plugins/action/set_stats.py +1 -2
  320. ansible/plugins/action/shell.py +1 -2
  321. ansible/plugins/action/template.py +1 -2
  322. ansible/plugins/action/unarchive.py +1 -2
  323. ansible/plugins/action/uri.py +2 -3
  324. ansible/plugins/action/validate_argument_spec.py +1 -2
  325. ansible/plugins/action/wait_for_connection.py +2 -3
  326. ansible/plugins/become/__init__.py +1 -2
  327. ansible/plugins/become/runas.py +1 -2
  328. ansible/plugins/become/su.py +1 -2
  329. ansible/plugins/become/sudo.py +1 -2
  330. ansible/plugins/cache/__init__.py +3 -2
  331. ansible/plugins/cache/base.py +1 -2
  332. ansible/plugins/cache/jsonfile.py +1 -3
  333. ansible/plugins/cache/memory.py +1 -2
  334. ansible/plugins/callback/__init__.py +2 -4
  335. ansible/plugins/callback/default.py +2 -3
  336. ansible/plugins/callback/junit.py +1 -2
  337. ansible/plugins/callback/minimal.py +1 -3
  338. ansible/plugins/callback/oneline.py +1 -3
  339. ansible/plugins/callback/tree.py +1 -2
  340. ansible/plugins/cliconf/__init__.py +1 -2
  341. ansible/plugins/connection/__init__.py +4 -5
  342. ansible/plugins/connection/local.py +3 -4
  343. ansible/plugins/connection/paramiko_ssh.py +1 -2
  344. ansible/plugins/connection/psrp.py +1 -2
  345. ansible/plugins/connection/ssh.py +18 -54
  346. ansible/plugins/connection/winrm.py +17 -6
  347. ansible/plugins/doc_fragments/action_common_attributes.py +2 -3
  348. ansible/plugins/doc_fragments/action_core.py +3 -4
  349. ansible/plugins/doc_fragments/backup.py +1 -2
  350. ansible/plugins/doc_fragments/connection_pipelining.py +1 -2
  351. ansible/plugins/doc_fragments/constructed.py +1 -2
  352. ansible/plugins/doc_fragments/decrypt.py +2 -3
  353. ansible/plugins/doc_fragments/default_callback.py +1 -2
  354. ansible/plugins/doc_fragments/files.py +1 -2
  355. ansible/plugins/doc_fragments/inventory_cache.py +1 -2
  356. ansible/plugins/doc_fragments/result_format_callback.py +1 -2
  357. ansible/plugins/doc_fragments/return_common.py +1 -2
  358. ansible/plugins/doc_fragments/shell_common.py +1 -2
  359. ansible/plugins/doc_fragments/shell_windows.py +1 -2
  360. ansible/plugins/doc_fragments/template_common.py +1 -2
  361. ansible/plugins/doc_fragments/url.py +1 -2
  362. ansible/plugins/doc_fragments/url_windows.py +1 -2
  363. ansible/plugins/doc_fragments/validate.py +1 -2
  364. ansible/plugins/doc_fragments/vars_plugin_staging.py +1 -2
  365. ansible/plugins/filter/__init__.py +1 -2
  366. ansible/plugins/filter/b64decode.yml +8 -8
  367. ansible/plugins/filter/b64encode.yml +4 -4
  368. ansible/plugins/filter/comment.yml +1 -1
  369. ansible/plugins/filter/core.py +11 -9
  370. ansible/plugins/filter/encryption.py +1 -3
  371. ansible/plugins/filter/extract.yml +1 -1
  372. ansible/plugins/filter/from_yaml_all.yml +1 -1
  373. ansible/plugins/filter/human_readable.yml +3 -3
  374. ansible/plugins/filter/human_to_bytes.yml +2 -2
  375. ansible/plugins/filter/mandatory.yml +1 -1
  376. ansible/plugins/filter/mathstuff.py +2 -2
  377. ansible/plugins/filter/password_hash.yml +3 -2
  378. ansible/plugins/filter/regex_replace.yml +15 -0
  379. ansible/plugins/filter/regex_search.yml +12 -0
  380. ansible/plugins/filter/strftime.yml +2 -9
  381. ansible/plugins/filter/to_datetime.yml +17 -2
  382. ansible/plugins/filter/to_nice_json.yml +4 -0
  383. ansible/plugins/filter/union.yml +1 -1
  384. ansible/plugins/filter/urls.py +1 -2
  385. ansible/plugins/filter/urlsplit.py +1 -2
  386. ansible/plugins/filter/zip.yml +2 -2
  387. ansible/plugins/filter/zip_longest.yml +1 -1
  388. ansible/plugins/httpapi/__init__.py +1 -2
  389. ansible/plugins/inventory/__init__.py +2 -4
  390. ansible/plugins/inventory/advanced_host_list.py +1 -2
  391. ansible/plugins/inventory/auto.py +2 -3
  392. ansible/plugins/inventory/constructed.py +3 -2
  393. ansible/plugins/inventory/generator.py +1 -2
  394. ansible/plugins/inventory/host_list.py +1 -2
  395. ansible/plugins/inventory/ini.py +1 -2
  396. ansible/plugins/inventory/script.py +122 -3
  397. ansible/plugins/inventory/toml.py +1 -2
  398. ansible/plugins/inventory/yaml.py +3 -4
  399. ansible/plugins/list.py +2 -3
  400. ansible/plugins/loader.py +10 -11
  401. ansible/plugins/lookup/__init__.py +1 -3
  402. ansible/plugins/lookup/config.py +19 -15
  403. ansible/plugins/lookup/csvfile.py +16 -7
  404. ansible/plugins/lookup/dict.py +2 -3
  405. ansible/plugins/lookup/env.py +4 -4
  406. ansible/plugins/lookup/file.py +1 -2
  407. ansible/plugins/lookup/fileglob.py +1 -2
  408. ansible/plugins/lookup/first_found.py +8 -7
  409. ansible/plugins/lookup/indexed_items.py +1 -2
  410. ansible/plugins/lookup/ini.py +6 -3
  411. ansible/plugins/lookup/inventory_hostnames.py +1 -2
  412. ansible/plugins/lookup/items.py +1 -2
  413. ansible/plugins/lookup/lines.py +1 -2
  414. ansible/plugins/lookup/list.py +1 -3
  415. ansible/plugins/lookup/nested.py +1 -2
  416. ansible/plugins/lookup/password.py +16 -14
  417. ansible/plugins/lookup/pipe.py +1 -2
  418. ansible/plugins/lookup/random_choice.py +1 -2
  419. ansible/plugins/lookup/sequence.py +21 -52
  420. ansible/plugins/lookup/subelements.py +1 -2
  421. ansible/plugins/lookup/template.py +1 -2
  422. ansible/plugins/lookup/together.py +1 -2
  423. ansible/plugins/lookup/unvault.py +1 -2
  424. ansible/plugins/lookup/url.py +9 -3
  425. ansible/plugins/lookup/varnames.py +1 -2
  426. ansible/plugins/lookup/vars.py +1 -2
  427. ansible/plugins/netconf/__init__.py +1 -2
  428. ansible/plugins/shell/__init__.py +3 -4
  429. ansible/plugins/shell/cmd.py +1 -2
  430. ansible/plugins/shell/powershell.py +1 -2
  431. ansible/plugins/shell/sh.py +1 -2
  432. ansible/plugins/strategy/__init__.py +33 -21
  433. ansible/plugins/strategy/debug.py +1 -2
  434. ansible/plugins/strategy/free.py +18 -8
  435. ansible/plugins/strategy/host_pinned.py +1 -3
  436. ansible/plugins/strategy/linear.py +23 -23
  437. ansible/plugins/terminal/__init__.py +2 -3
  438. ansible/plugins/test/__init__.py +1 -2
  439. ansible/plugins/test/change.yml +1 -1
  440. ansible/plugins/test/changed.yml +1 -1
  441. ansible/plugins/test/contains.yml +1 -1
  442. ansible/plugins/test/core.py +2 -4
  443. ansible/plugins/test/exists.yml +1 -1
  444. ansible/plugins/test/failed.yml +1 -1
  445. ansible/plugins/test/failure.yml +1 -1
  446. ansible/plugins/test/files.py +1 -3
  447. ansible/plugins/test/finished.yml +3 -3
  448. ansible/plugins/test/issuperset.yml +1 -1
  449. ansible/plugins/test/match.yml +1 -1
  450. ansible/plugins/test/mathstuff.py +1 -2
  451. ansible/plugins/test/reachable.yml +1 -1
  452. ansible/plugins/test/regex.yml +1 -1
  453. ansible/plugins/test/search.yml +1 -1
  454. ansible/plugins/test/skip.yml +1 -1
  455. ansible/plugins/test/skipped.yml +1 -1
  456. ansible/plugins/test/started.yml +1 -1
  457. ansible/plugins/test/succeeded.yml +1 -1
  458. ansible/plugins/test/success.yml +1 -1
  459. ansible/plugins/test/successful.yml +1 -1
  460. ansible/plugins/test/superset.yml +1 -1
  461. ansible/plugins/test/unreachable.yml +1 -1
  462. ansible/plugins/test/uri.py +1 -3
  463. ansible/plugins/vars/__init__.py +1 -2
  464. ansible/plugins/vars/host_group_vars.py +2 -3
  465. ansible/release.py +3 -5
  466. ansible/template/__init__.py +14 -27
  467. ansible/template/native_helpers.py +1 -3
  468. ansible/template/template.py +1 -3
  469. ansible/template/vars.py +1 -0
  470. ansible/utils/__init__.py +1 -3
  471. ansible/utils/cmd_functions.py +1 -2
  472. ansible/utils/collection_loader/__init__.py +1 -2
  473. ansible/utils/collection_loader/_collection_config.py +1 -2
  474. ansible/utils/collection_loader/_collection_finder.py +1 -2
  475. ansible/utils/collection_loader/_collection_meta.py +1 -2
  476. ansible/utils/color.py +1 -2
  477. ansible/utils/context_objects.py +1 -4
  478. ansible/utils/display.py +88 -30
  479. ansible/utils/encrypt.py +4 -105
  480. ansible/utils/fqcn.py +1 -2
  481. ansible/utils/galaxy.py +1 -3
  482. ansible/utils/hashing.py +1 -3
  483. ansible/utils/helpers.py +1 -3
  484. ansible/utils/jsonrpc.py +1 -2
  485. ansible/utils/listify.py +1 -3
  486. ansible/utils/lock.py +1 -3
  487. ansible/utils/multiprocessing.py +1 -3
  488. ansible/utils/native_jinja.py +1 -3
  489. ansible/utils/path.py +1 -2
  490. ansible/utils/plugin_docs.py +7 -6
  491. ansible/utils/py3compat.py +17 -55
  492. ansible/utils/sentinel.py +1 -3
  493. ansible/utils/shlex.py +1 -3
  494. ansible/utils/singleton.py +1 -3
  495. ansible/utils/ssh_functions.py +1 -3
  496. ansible/utils/unicode.py +1 -3
  497. ansible/utils/unsafe_proxy.py +1 -2
  498. ansible/utils/vars.py +6 -8
  499. ansible/utils/version.py +1 -3
  500. ansible/vars/clean.py +1 -3
  501. ansible/vars/fact_cache.py +1 -2
  502. ansible/vars/hostvars.py +9 -29
  503. ansible/vars/manager.py +24 -6
  504. ansible/vars/reserved.py +1 -3
  505. {ansible_core-2.16.5.data → ansible_core-2.17.0b1.data}/scripts/ansible-test +1 -2
  506. {ansible_core-2.16.5.dist-info → ansible_core-2.17.0b1.dist-info}/METADATA +3 -3
  507. ansible_core-2.17.0b1.dist-info/RECORD +987 -0
  508. ansible_test/__init__.py +1 -2
  509. ansible_test/_data/completion/docker.txt +7 -9
  510. ansible_test/_data/completion/remote.txt +6 -7
  511. ansible_test/_data/requirements/ansible-test.txt +0 -2
  512. ansible_test/_data/requirements/constraints.txt +1 -6
  513. ansible_test/_data/requirements/sanity.ansible-doc.txt +3 -3
  514. ansible_test/_data/requirements/sanity.changelog.txt +3 -3
  515. ansible_test/_data/requirements/sanity.import.plugin.txt +2 -2
  516. ansible_test/_data/requirements/sanity.mypy.txt +12 -12
  517. ansible_test/_data/requirements/sanity.pep8.txt +1 -1
  518. ansible_test/_data/requirements/sanity.pylint.txt +7 -7
  519. ansible_test/_data/requirements/sanity.runtime-metadata.txt +1 -1
  520. ansible_test/_data/requirements/sanity.validate-modules.txt +3 -3
  521. ansible_test/_data/requirements/sanity.yamllint.txt +2 -2
  522. ansible_test/_internal/bootstrap.py +2 -2
  523. ansible_test/_internal/classification/__init__.py +0 -5
  524. ansible_test/_internal/commands/integration/cloud/cs.py +1 -1
  525. ansible_test/_internal/commands/integration/cloud/nios.py +1 -1
  526. ansible_test/_internal/commands/sanity/__init__.py +1 -27
  527. ansible_test/_internal/commands/sanity/ansible_doc.py +1 -1
  528. ansible_test/_internal/commands/sanity/import.py +0 -18
  529. ansible_test/_internal/commands/sanity/mypy.py +7 -10
  530. ansible_test/_internal/commands/units/__init__.py +1 -1
  531. ansible_test/_internal/config.py +0 -1
  532. ansible_test/_internal/content_config.py +0 -5
  533. ansible_test/_internal/coverage_util.py +0 -1
  534. ansible_test/_internal/docker_util.py +1 -1
  535. ansible_test/_internal/host_profiles.py +5 -4
  536. ansible_test/_internal/python_requirements.py +1 -119
  537. ansible_test/_internal/ssh.py +1 -0
  538. ansible_test/_internal/util.py +1 -1
  539. ansible_test/_internal/util_common.py +1 -1
  540. ansible_test/_internal/venv.py +10 -108
  541. ansible_test/_util/__init__.py +1 -2
  542. ansible_test/_util/controller/sanity/mypy/ansible-core.ini +0 -6
  543. ansible_test/_util/controller/sanity/mypy/modules.ini +0 -6
  544. ansible_test/_util/controller/sanity/pylint/config/ansible-test-target.cfg +0 -1
  545. ansible_test/_util/controller/sanity/pylint/config/ansible-test.cfg +0 -1
  546. ansible_test/_util/controller/sanity/pylint/config/code-smell.cfg +0 -1
  547. ansible_test/_util/controller/sanity/pylint/config/collection.cfg +0 -1
  548. ansible_test/_util/controller/sanity/pylint/config/default.cfg +0 -1
  549. ansible_test/_util/controller/sanity/pylint/plugins/deprecated.py +1 -2
  550. ansible_test/_util/controller/sanity/shellcheck/exclude.txt +0 -1
  551. ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py +31 -59
  552. ansible_test/_util/controller/sanity/validate-modules/validate_modules/module_args.py +0 -7
  553. ansible_test/_util/controller/sanity/validate-modules/validate_modules/schema.py +10 -2
  554. ansible_test/_util/controller/sanity/validate-modules/validate_modules/utils.py +1 -1
  555. ansible_test/_util/controller/sanity/yamllint/yamllinter.py +16 -4
  556. ansible_test/_util/target/__init__.py +1 -2
  557. ansible_test/_util/target/cli/ansible_test_cli_stub.py +1 -2
  558. ansible_test/_util/target/common/constants.py +1 -4
  559. ansible_test/_util/target/injector/python.py +4 -19
  560. ansible_test/_util/target/pytest/plugins/ansible_forked.py +2 -9
  561. ansible_test/_util/target/pytest/plugins/ansible_pytest_collections.py +1 -5
  562. ansible_test/_util/target/pytest/plugins/ansible_pytest_coverage.py +1 -2
  563. ansible_test/_util/target/sanity/compile/compile.py +3 -12
  564. ansible_test/_util/target/sanity/import/importer.py +1 -12
  565. ansible_test/_util/target/setup/bootstrap.sh +49 -105
  566. ansible_test/_util/target/setup/probe_cgroups.py +1 -2
  567. ansible_test/_util/target/setup/quiet_pip.py +1 -16
  568. ansible_test/_util/target/setup/requirements.py +9 -2
  569. ansible_test/_util/target/tools/virtualenvcheck.py +1 -2
  570. ansible_test/_util/target/tools/yamlcheck.py +1 -2
  571. ansible/module_utils/common/_json_compat.py +0 -16
  572. ansible/module_utils/compat/_selectors2.py +0 -655
  573. ansible/modules/yum.py +0 -1821
  574. ansible/plugins/action/yum.py +0 -111
  575. ansible_core-2.16.5.dist-info/RECORD +0 -1009
  576. ansible_test/_util/controller/sanity/code-smell/future-import-boilerplate.json +0 -7
  577. ansible_test/_util/controller/sanity/code-smell/future-import-boilerplate.py +0 -46
  578. ansible_test/_util/controller/sanity/code-smell/metaclass-boilerplate.json +0 -7
  579. ansible_test/_util/controller/sanity/code-smell/metaclass-boilerplate.py +0 -44
  580. ansible_test/_util/controller/sanity/code-smell/no-basestring.json +0 -7
  581. ansible_test/_util/controller/sanity/code-smell/no-basestring.py +0 -21
  582. ansible_test/_util/controller/sanity/code-smell/no-dict-iteritems.json +0 -7
  583. ansible_test/_util/controller/sanity/code-smell/no-dict-iteritems.py +0 -21
  584. ansible_test/_util/controller/sanity/code-smell/no-dict-iterkeys.json +0 -7
  585. ansible_test/_util/controller/sanity/code-smell/no-dict-iterkeys.py +0 -21
  586. ansible_test/_util/controller/sanity/code-smell/no-dict-itervalues.json +0 -7
  587. ansible_test/_util/controller/sanity/code-smell/no-dict-itervalues.py +0 -21
  588. ansible_test/_util/controller/sanity/code-smell/no-main-display.json +0 -10
  589. ansible_test/_util/controller/sanity/code-smell/no-main-display.py +0 -21
  590. ansible_test/_util/controller/sanity/code-smell/no-unicode-literals.json +0 -7
  591. ansible_test/_util/controller/sanity/code-smell/no-unicode-literals.py +0 -21
  592. ansible_test/_util/controller/tools/sslcheck.py +0 -22
  593. ansible_test/_util/target/common/__init__.py +0 -2
  594. {ansible_core-2.16.5.dist-info → ansible_core-2.17.0b1.dist-info}/COPYING +0 -0
  595. {ansible_core-2.16.5.dist-info → ansible_core-2.17.0b1.dist-info}/WHEEL +0 -0
  596. {ansible_core-2.16.5.dist-info → ansible_core-2.17.0b1.dist-info}/entry_points.txt +0 -0
  597. {ansible_core-2.16.5.dist-info → ansible_core-2.17.0b1.dist-info}/top_level.txt +0 -0
ansible/modules/dnf.py CHANGED
@@ -6,8 +6,7 @@
6
6
  #
7
7
  # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
8
8
 
9
- from __future__ import absolute_import, division, print_function
10
- __metaclass__ = type
9
+ from __future__ import annotations
11
10
 
12
11
 
13
12
  DOCUMENTATION = '''
@@ -22,7 +21,7 @@ options:
22
21
  description:
23
22
  - By default, this module will select the backend based on the C(ansible_pkg_mgr) fact.
24
23
  default: "auto"
25
- choices: [ auto, dnf4, dnf5 ]
24
+ choices: [ auto, yum, yum4, dnf4, dnf5 ]
26
25
  type: str
27
26
  version_added: 2.15
28
27
  name:
@@ -207,8 +206,8 @@ options:
207
206
  version_added: "2.7"
208
207
  install_repoquery:
209
208
  description:
210
- - This is effectively a no-op in DNF as it is not needed with DNF, but is an accepted parameter for feature
211
- parity/compatibility with the M(ansible.builtin.yum) module.
209
+ - This is effectively a no-op in DNF as it is not needed with DNF.
210
+ - This option is deprecated and will be removed in ansible-core 2.20.
212
211
  type: bool
213
212
  default: "yes"
214
213
  version_added: "2.7"
@@ -246,11 +245,19 @@ options:
246
245
  version_added: "2.10"
247
246
  nobest:
248
247
  description:
249
- - Set best option to False, so that transactions are not limited to best candidates only.
248
+ - This is the opposite of the O(best) option kept for backwards compatibility.
249
+ - Since ansible-core 2.17 the default value is set by the operating system distribution.
250
250
  required: false
251
251
  type: bool
252
- default: "no"
253
252
  version_added: "2.11"
253
+ best:
254
+ description:
255
+ - When set to V(true), either use a package with the highest version available or fail.
256
+ - When set to V(false), if the latest version cannot be installed go with the lower version.
257
+ - Default is set by the operating system distribution.
258
+ required: false
259
+ type: bool
260
+ version_added: "2.17"
254
261
  cacheonly:
255
262
  description:
256
263
  - Tells dnf to run entirely from system cache; does not download or update metadata.
@@ -262,7 +269,7 @@ extends_documentation_fragment:
262
269
  - action_common_attributes.flow
263
270
  attributes:
264
271
  action:
265
- details: In the case of dnf, it has 2 action plugins that use it under the hood, M(ansible.builtin.yum) and M(ansible.builtin.package).
272
+ details: dnf has 2 action plugins that use it under the hood, M(ansible.builtin.dnf) and M(ansible.builtin.package).
266
273
  support: partial
267
274
  async:
268
275
  support: none
@@ -380,7 +387,6 @@ EXAMPLES = '''
380
387
  '''
381
388
 
382
389
  import os
383
- import re
384
390
  import sys
385
391
 
386
392
  from ansible.module_utils.common.text.converters import to_native, to_text
@@ -410,7 +416,6 @@ class DnfModule(YumDnf):
410
416
  super(DnfModule, self).__init__(module)
411
417
 
412
418
  self._ensure_dnf()
413
- self.lockfile = "/var/cache/dnf/*_lock.pid"
414
419
  self.pkg_mgr_name = "dnf"
415
420
 
416
421
  try:
@@ -418,15 +423,6 @@ class DnfModule(YumDnf):
418
423
  except AttributeError:
419
424
  self.with_modules = False
420
425
 
421
- # DNF specific args that are not part of YumDnf
422
- self.allowerasing = self.module.params['allowerasing']
423
- self.nobest = self.module.params['nobest']
424
-
425
- def is_lockfile_pid_valid(self):
426
- # FIXME? it looks like DNF takes care of invalid lock files itself?
427
- # https://github.com/ansible/ansible/issues/57189
428
- return True
429
-
430
426
  def _sanitize_dnf_error_msg_install(self, spec, error):
431
427
  """
432
428
  For unhandled dnf.exceptions.Error scenarios, there are certain error
@@ -468,7 +464,7 @@ class DnfModule(YumDnf):
468
464
  'version': package.version,
469
465
  'repo': package.repoid}
470
466
 
471
- # envra format for alignment with the yum module
467
+ # envra format for backwards compat
472
468
  result['envra'] = '{epoch}:{name}-{version}-{release}.{arch}'.format(**result)
473
469
 
474
470
  # keep nevra key for backwards compat as it was previously
@@ -482,94 +478,6 @@ class DnfModule(YumDnf):
482
478
 
483
479
  return result
484
480
 
485
- def _split_package_arch(self, packagename):
486
- # This list was auto generated on a Fedora 28 system with the following one-liner
487
- # printf '[ '; for arch in $(ls /usr/lib/rpm/platform); do printf '"%s", ' ${arch%-linux}; done; printf ']\n'
488
- redhat_rpm_arches = [
489
- "aarch64", "alphaev56", "alphaev5", "alphaev67", "alphaev6", "alpha",
490
- "alphapca56", "amd64", "armv3l", "armv4b", "armv4l", "armv5tejl", "armv5tel",
491
- "armv5tl", "armv6hl", "armv6l", "armv7hl", "armv7hnl", "armv7l", "athlon",
492
- "geode", "i386", "i486", "i586", "i686", "ia32e", "ia64", "m68k", "mips64el",
493
- "mips64", "mips64r6el", "mips64r6", "mipsel", "mips", "mipsr6el", "mipsr6",
494
- "noarch", "pentium3", "pentium4", "ppc32dy4", "ppc64iseries", "ppc64le", "ppc64",
495
- "ppc64p7", "ppc64pseries", "ppc8260", "ppc8560", "ppciseries", "ppc", "ppcpseries",
496
- "riscv64", "s390", "s390x", "sh3", "sh4a", "sh4", "sh", "sparc64", "sparc64v",
497
- "sparc", "sparcv8", "sparcv9", "sparcv9v", "x86_64"
498
- ]
499
-
500
- name, delimiter, arch = packagename.rpartition('.')
501
- if name and arch and arch in redhat_rpm_arches:
502
- return name, arch
503
- return packagename, None
504
-
505
- def _packagename_dict(self, packagename):
506
- """
507
- Return a dictionary of information for a package name string or None
508
- if the package name doesn't contain at least all NVR elements
509
- """
510
-
511
- if packagename[-4:] == '.rpm':
512
- packagename = packagename[:-4]
513
-
514
- rpm_nevr_re = re.compile(r'(\S+)-(?:(\d*):)?(.*)-(~?\w+[\w.+]*)')
515
- try:
516
- arch = None
517
- nevr, arch = self._split_package_arch(packagename)
518
- if arch:
519
- packagename = nevr
520
- rpm_nevr_match = rpm_nevr_re.match(packagename)
521
- if rpm_nevr_match:
522
- name, epoch, version, release = rpm_nevr_re.match(packagename).groups()
523
- if not version or not version.split('.')[0].isdigit():
524
- return None
525
- else:
526
- return None
527
- except AttributeError as e:
528
- self.module.fail_json(
529
- msg='Error attempting to parse package: %s, %s' % (packagename, to_native(e)),
530
- rc=1,
531
- results=[]
532
- )
533
-
534
- if not epoch:
535
- epoch = "0"
536
-
537
- if ':' in name:
538
- epoch_name = name.split(":")
539
-
540
- epoch = epoch_name[0]
541
- name = ''.join(epoch_name[1:])
542
-
543
- result = {
544
- 'name': name,
545
- 'epoch': epoch,
546
- 'release': release,
547
- 'version': version,
548
- }
549
-
550
- return result
551
-
552
- # Original implementation from yum.rpmUtils.miscutils (GPLv2+)
553
- # http://yum.baseurl.org/gitweb?p=yum.git;a=blob;f=rpmUtils/miscutils.py
554
- def _compare_evr(self, e1, v1, r1, e2, v2, r2):
555
- # return 1: a is newer than b
556
- # 0: a and b are the same version
557
- # -1: b is newer than a
558
- if e1 is None:
559
- e1 = '0'
560
- else:
561
- e1 = str(e1)
562
- v1 = str(v1)
563
- r1 = str(r1)
564
- if e2 is None:
565
- e2 = '0'
566
- else:
567
- e2 = str(e2)
568
- v2 = str(v2)
569
- r2 = str(r2)
570
- rc = dnf.rpm.rpm.labelCompare((e1, v1, r1), (e2, v2, r2))
571
- return rc
572
-
573
481
  def _ensure_dnf(self):
574
482
  locale = get_best_parsable_locale(self.module)
575
483
  os.environ['LC_ALL'] = os.environ['LC_MESSAGES'] = locale
@@ -578,7 +486,6 @@ class DnfModule(YumDnf):
578
486
  global dnf
579
487
  try:
580
488
  import dnf
581
- import dnf.cli
582
489
  import dnf.const
583
490
  import dnf.exceptions
584
491
  import dnf.package
@@ -689,9 +596,11 @@ class DnfModule(YumDnf):
689
596
  if self.skip_broken:
690
597
  conf.strict = 0
691
598
 
692
- # Set best
693
- if self.nobest:
694
- conf.best = 0
599
+ # best and nobest are mutually exclusive
600
+ if self.nobest is not None:
601
+ conf.best = not self.nobest
602
+ elif self.best is not None:
603
+ conf.best = self.best
695
604
 
696
605
  if self.download_only:
697
606
  conf.downloadonly = True
@@ -724,6 +633,11 @@ class DnfModule(YumDnf):
724
633
  for repo in repos.get_matching(repo_pattern):
725
634
  repo.enable()
726
635
 
636
+ for repo in base.repos.iter_enabled():
637
+ if self.disable_gpg_check:
638
+ repo.gpgcheck = False
639
+ repo.repo_gpgcheck = False
640
+
727
641
  def _base(self, conf_file, disable_gpg_check, disablerepo, enablerepo, installroot, sslverify):
728
642
  """Return a fully configured dnf Base object."""
729
643
  base = dnf.Base()
@@ -809,48 +723,28 @@ class DnfModule(YumDnf):
809
723
  self.module.exit_json(msg="", results=results)
810
724
 
811
725
  def _is_installed(self, pkg):
812
- installed = self.base.sack.query().installed()
813
-
814
- package_spec = {}
815
- name, arch = self._split_package_arch(pkg)
816
- if arch:
817
- package_spec['arch'] = arch
818
-
819
- package_details = self._packagename_dict(pkg)
820
- if package_details:
821
- package_details['epoch'] = int(package_details['epoch'])
822
- package_spec.update(package_details)
823
- else:
824
- package_spec['name'] = name
825
-
826
- return bool(installed.filter(**package_spec))
726
+ return bool(
727
+ dnf.subject.Subject(pkg).get_best_query(sack=self.base.sack).installed().run()
728
+ )
827
729
 
828
730
  def _is_newer_version_installed(self, pkg_name):
829
- candidate_pkg = self._packagename_dict(pkg_name)
830
- if not candidate_pkg:
831
- # The user didn't provide a versioned rpm, so version checking is
832
- # not required
833
- return False
834
-
835
- installed = self.base.sack.query().installed()
836
- installed_pkg = installed.filter(name=candidate_pkg['name']).run()
837
- if installed_pkg:
838
- installed_pkg = installed_pkg[0]
839
-
840
- # this looks weird but one is a dict and the other is a dnf.Package
841
- evr_cmp = self._compare_evr(
842
- installed_pkg.epoch, installed_pkg.version, installed_pkg.release,
843
- candidate_pkg['epoch'], candidate_pkg['version'], candidate_pkg['release'],
844
- )
845
-
846
- return evr_cmp == 1
847
- else:
731
+ try:
732
+ if isinstance(pkg_name, dnf.package.Package):
733
+ available = pkg_name
734
+ else:
735
+ available = sorted(
736
+ dnf.subject.Subject(pkg_name).get_best_query(sack=self.base.sack).available().run()
737
+ )[-1]
738
+ installed = sorted(self.base.sack.query().installed().filter(name=available.name).run())[-1]
739
+ except IndexError:
848
740
  return False
741
+ return installed > available
849
742
 
850
743
  def _mark_package_install(self, pkg_spec, upgrade=False):
851
744
  """Mark the package for install."""
852
745
  is_newer_version_installed = self._is_newer_version_installed(pkg_spec)
853
746
  is_installed = self._is_installed(pkg_spec)
747
+ msg = ''
854
748
  try:
855
749
  if is_newer_version_installed:
856
750
  if self.allow_downgrade:
@@ -884,18 +778,16 @@ class DnfModule(YumDnf):
884
778
  pass
885
779
  else: # Case 7, The package is not installed, simply install it
886
780
  self.base.install(pkg_spec, strict=self.base.conf.strict)
887
-
888
- return {'failed': False, 'msg': '', 'failure': '', 'rc': 0}
889
-
890
781
  except dnf.exceptions.MarkingError as e:
891
- return {
892
- 'failed': True,
893
- 'msg': "No package {0} available.".format(pkg_spec),
894
- 'failure': " ".join((pkg_spec, to_native(e))),
895
- 'rc': 1,
896
- "results": []
897
- }
898
-
782
+ msg = "No package {0} available.".format(pkg_spec)
783
+ if self.base.conf.strict:
784
+ return {
785
+ 'failed': True,
786
+ 'msg': msg,
787
+ 'failure': " ".join((pkg_spec, to_native(e))),
788
+ 'rc': 1,
789
+ "results": []
790
+ }
899
791
  except dnf.exceptions.DepsolveError as e:
900
792
  return {
901
793
  'failed': True,
@@ -904,7 +796,6 @@ class DnfModule(YumDnf):
904
796
  'rc': 1,
905
797
  "results": []
906
798
  }
907
-
908
799
  except dnf.exceptions.Error as e:
909
800
  if to_text("already installed") in to_text(e):
910
801
  return {'failed': False, 'msg': '', 'failure': ''}
@@ -917,16 +808,7 @@ class DnfModule(YumDnf):
917
808
  "results": []
918
809
  }
919
810
 
920
- def _whatprovides(self, filepath):
921
- self.base.read_all_repos()
922
- available = self.base.sack.query().available()
923
- # Search in file
924
- files_filter = available.filter(file=filepath)
925
- # And Search in provides
926
- pkg_spec = files_filter.union(available.filter(provides=filepath)).run()
927
-
928
- if pkg_spec:
929
- return pkg_spec[0].name
811
+ return {'failed': False, 'msg': msg, 'failure': '', 'rc': 0}
930
812
 
931
813
  def _parse_spec_group_file(self):
932
814
  pkg_specs, grp_specs, module_specs, filenames = [], [], [], []
@@ -939,11 +821,13 @@ class DnfModule(YumDnf):
939
821
  elif name.endswith(".rpm"):
940
822
  filenames.append(name)
941
823
  elif name.startswith('/'):
942
- # like "dnf install /usr/bin/vi"
943
- pkg_spec = self._whatprovides(name)
944
- if pkg_spec:
945
- pkg_specs.append(pkg_spec)
946
- continue
824
+ # dnf install /usr/bin/vi
825
+ installed = self.base.sack.query().filter(provides=name, file=name).installed().run()
826
+ if installed:
827
+ pkg_specs.append(installed[0].name) # should be only one?
828
+ elif not self.update_only:
829
+ # not installed, pass the filename for dnf to process
830
+ pkg_specs.append(name)
947
831
  elif name.startswith("@") or ('/' in name):
948
832
  if not already_loaded_comps:
949
833
  self.base.read_comps()
@@ -1005,7 +889,7 @@ class DnfModule(YumDnf):
1005
889
  else:
1006
890
  for pkg in pkgs:
1007
891
  try:
1008
- if self._is_newer_version_installed(self._package_dict(pkg)['nevra']):
892
+ if self._is_newer_version_installed(pkg):
1009
893
  if self.allow_downgrade:
1010
894
  self.base.package_install(pkg, strict=self.base.conf.strict)
1011
895
  else:
@@ -1201,13 +1085,6 @@ class DnfModule(YumDnf):
1201
1085
  response['results'].append("Packages providing %s not installed due to update_only specified" % spec)
1202
1086
  else:
1203
1087
  for pkg_spec in pkg_specs:
1204
- # Previously we forced base.conf.best=True here.
1205
- # However in 2.11+ there is a self.nobest option, so defer to that.
1206
- # Note, however, that just because nobest isn't set, doesn't mean that
1207
- # base.conf.best is actually true. We only force it false in
1208
- # _configure_base(), we never set it to true, and it can default to false.
1209
- # Thus, we still need to explicitly set it here.
1210
- self.base.conf.best = not self.nobest
1211
1088
  install_result = self._mark_package_install(pkg_spec, upgrade=True)
1212
1089
  if install_result['failed']:
1213
1090
  if install_result['msg']:
@@ -1441,8 +1318,10 @@ class DnfModule(YumDnf):
1441
1318
 
1442
1319
  if self.with_modules:
1443
1320
  self.module_base = dnf.module.module_base.ModuleBase(self.base)
1444
-
1445
- self.ensure()
1321
+ try:
1322
+ self.ensure()
1323
+ finally:
1324
+ self.base.close()
1446
1325
 
1447
1326
 
1448
1327
  def main():
@@ -1457,11 +1336,7 @@ def main():
1457
1336
  # list=repos
1458
1337
  # list=pkgspec
1459
1338
 
1460
- # Extend yumdnf_argument_spec with dnf-specific features that will never be
1461
- # backported to yum because yum is now in "maintenance mode" upstream
1462
- yumdnf_argument_spec['argument_spec']['allowerasing'] = dict(default=False, type='bool')
1463
- yumdnf_argument_spec['argument_spec']['nobest'] = dict(default=False, type='bool')
1464
- yumdnf_argument_spec['argument_spec']['use_backend'] = dict(default='auto', choices=['auto', 'dnf4', 'dnf5'])
1339
+ yumdnf_argument_spec['argument_spec']['use_backend'] = dict(default='auto', choices=['auto', 'yum', 'yum4', 'dnf4', 'dnf5'])
1465
1340
 
1466
1341
  module = AnsibleModule(
1467
1342
  **yumdnf_argument_spec
ansible/modules/dnf5.py CHANGED
@@ -2,9 +2,8 @@
2
2
  # Copyright 2023 Ansible Project
3
3
  # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
4
4
 
5
- from __future__ import absolute_import, division, print_function
5
+ from __future__ import annotations
6
6
 
7
- __metaclass__ = type
8
7
 
9
8
  DOCUMENTATION = """
10
9
  module: dnf5
@@ -152,7 +151,7 @@ options:
152
151
  validate_certs:
153
152
  description:
154
153
  - This is effectively a no-op in the dnf5 module as dnf5 itself handles downloading a https url as the source of the rpm,
155
- but is an accepted parameter for feature parity/compatibility with the M(ansible.builtin.yum) module.
154
+ but is an accepted parameter for feature parity/compatibility with the M(ansible.builtin.dnf) module.
156
155
  type: bool
157
156
  default: "yes"
158
157
  sslverify:
@@ -175,8 +174,8 @@ options:
175
174
  default: "no"
176
175
  install_repoquery:
177
176
  description:
178
- - This is effectively a no-op in DNF as it is not needed with DNF, but is an accepted parameter for feature
179
- parity/compatibility with the M(ansible.builtin.yum) module.
177
+ - This is effectively a no-op in DNF as it is not needed with DNF.
178
+ - This option is deprecated and will be removed in ansible-core 2.20.
180
179
  type: bool
181
180
  default: "yes"
182
181
  download_only:
@@ -209,10 +208,18 @@ options:
209
208
  default: "no"
210
209
  nobest:
211
210
  description:
212
- - Set best option to False, so that transactions are not limited to best candidates only.
211
+ - This is the opposite of the O(best) option kept for backwards compatibility.
212
+ - Since ansible-core 2.17 the default value is set by the operating system distribution.
213
213
  required: false
214
214
  type: bool
215
- default: "no"
215
+ best:
216
+ description:
217
+ - When set to V(true), either use a package with the highest version available or fail.
218
+ - When set to V(false), if the latest version cannot be installed go with the lower version.
219
+ - Default is set by the operating system distribution.
220
+ required: false
221
+ type: bool
222
+ version_added: "2.17"
216
223
  cacheonly:
217
224
  description:
218
225
  - Tells dnf to run entirely from system cache; does not download or update metadata.
@@ -223,7 +230,7 @@ extends_documentation_fragment:
223
230
  - action_common_attributes.flow
224
231
  attributes:
225
232
  action:
226
- details: In the case of dnf, it has 2 action plugins that use it under the hood, M(ansible.builtin.yum) and M(ansible.builtin.package).
233
+ details: dnf5 has 2 action plugins that use it under the hood, M(ansible.builtin.dnf) and M(ansible.builtin.package).
227
234
  support: partial
228
235
  async:
229
236
  support: none
@@ -357,23 +364,47 @@ def is_installed(base, spec):
357
364
 
358
365
 
359
366
  def is_newer_version_installed(base, spec):
367
+ # FIXME investigate whether this function can be replaced by dnf5's allow_downgrade option
368
+ if "/" in spec:
369
+ spec = spec.split("/")[-1]
370
+ if spec.endswith(".rpm"):
371
+ spec = spec[:-4]
372
+
360
373
  try:
361
374
  spec_nevra = next(iter(libdnf5.rpm.Nevra.parse(spec)))
362
- except RuntimeError:
375
+ except (RuntimeError, StopIteration):
363
376
  return False
364
- spec_name = spec_nevra.get_name()
365
- v = spec_nevra.get_version()
366
- r = spec_nevra.get_release()
367
- if not v or not r:
377
+
378
+ spec_version = spec_nevra.get_version()
379
+ if not spec_version:
368
380
  return False
369
- spec_evr = "{}:{}-{}".format(spec_nevra.get_epoch() or "0", v, r)
370
381
 
371
- query = libdnf5.rpm.PackageQuery(base)
372
- query.filter_installed()
373
- query.filter_name([spec_name])
374
- query.filter_evr([spec_evr], libdnf5.common.QueryCmp_GT)
382
+ installed = libdnf5.rpm.PackageQuery(base)
383
+ installed.filter_installed()
384
+ installed.filter_name([spec_nevra.get_name()])
385
+ installed.filter_latest_evr()
386
+ try:
387
+ installed_package = list(installed)[-1]
388
+ except IndexError:
389
+ return False
390
+
391
+ target = libdnf5.rpm.PackageQuery(base)
392
+ target.filter_name([spec_nevra.get_name()])
393
+ target.filter_version([spec_version])
394
+ spec_release = spec_nevra.get_release()
395
+ if spec_release:
396
+ target.filter_release([spec_release])
397
+ spec_epoch = spec_nevra.get_epoch()
398
+ if spec_epoch:
399
+ target.filter_epoch([spec_epoch])
400
+ target.filter_latest_evr()
401
+ try:
402
+ target_package = list(target)[-1]
403
+ except IndexError:
404
+ return False
375
405
 
376
- return query.size() > 0
406
+ # FIXME https://github.com/rpm-software-management/dnf5/issues/1104
407
+ return libdnf5.rpm.rpmvercmp(installed_package.get_evr(), target_package.get_evr()) == 1
377
408
 
378
409
 
379
410
  def package_to_dict(package):
@@ -394,8 +425,7 @@ def get_unneeded_pkgs(base):
394
425
  query = libdnf5.rpm.PackageQuery(base)
395
426
  query.filter_installed()
396
427
  query.filter_unneeded()
397
- for pkg in query:
398
- yield pkg
428
+ yield from query
399
429
 
400
430
 
401
431
  class Dnf5Module(YumDnf):
@@ -403,14 +433,8 @@ class Dnf5Module(YumDnf):
403
433
  super(Dnf5Module, self).__init__(module)
404
434
  self._ensure_dnf()
405
435
 
406
- # FIXME https://github.com/rpm-software-management/dnf5/issues/402
407
- self.lockfile = ""
408
436
  self.pkg_mgr_name = "dnf5"
409
437
 
410
- # DNF specific args that are not part of YumDnf
411
- self.allowerasing = self.module.params["allowerasing"]
412
- self.nobest = self.module.params["nobest"]
413
-
414
438
  def _ensure_dnf(self):
415
439
  locale = get_best_parsable_locale(self.module)
416
440
  os.environ["LC_ALL"] = os.environ["LC_MESSAGES"] = locale
@@ -452,10 +476,6 @@ class Dnf5Module(YumDnf):
452
476
  failures=[],
453
477
  )
454
478
 
455
- def is_lockfile_pid_valid(self):
456
- # FIXME https://github.com/rpm-software-management/dnf5/issues/402
457
- return True
458
-
459
479
  def run(self):
460
480
  if sys.version_info.major < 3:
461
481
  self.module.fail_json(
@@ -503,7 +523,11 @@ class Dnf5Module(YumDnf):
503
523
  self.disable_excludes = "*"
504
524
  conf.disable_excludes = self.disable_excludes
505
525
  conf.skip_broken = self.skip_broken
506
- conf.best = not self.nobest
526
+ # best and nobest are mutually exclusive
527
+ if self.nobest is not None:
528
+ conf.best = not self.nobest
529
+ elif self.best is not None:
530
+ conf.best = self.best
507
531
  conf.install_weak_deps = self.install_weak_deps
508
532
  conf.gpgcheck = not self.disable_gpg_check
509
533
  conf.localpkg_gpgcheck = not self.disable_gpg_check
@@ -597,13 +621,7 @@ class Dnf5Module(YumDnf):
597
621
  for spec in self.names:
598
622
  if is_newer_version_installed(base, spec):
599
623
  if self.allow_downgrade:
600
- if upgrade:
601
- if is_installed(base, spec):
602
- goal.add_upgrade(spec, settings)
603
- else:
604
- goal.add_install(spec, settings)
605
- else:
606
- goal.add_install(spec, settings)
624
+ goal.add_install(spec, settings)
607
625
  elif is_installed(base, spec):
608
626
  if upgrade:
609
627
  goal.add_upgrade(spec, settings)
@@ -697,10 +715,6 @@ class Dnf5Module(YumDnf):
697
715
 
698
716
 
699
717
  def main():
700
- # Extend yumdnf_argument_spec with dnf-specific features that will never be
701
- # backported to yum because yum is now in "maintenance mode" upstream
702
- yumdnf_argument_spec["argument_spec"]["allowerasing"] = dict(default=False, type="bool")
703
- yumdnf_argument_spec["argument_spec"]["nobest"] = dict(default=False, type="bool")
704
718
  Dnf5Module(AnsibleModule(**yumdnf_argument_spec)).run()
705
719
 
706
720
 
@@ -3,8 +3,7 @@
3
3
  # Copyright: Ansible Project
4
4
  # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
5
5
 
6
- from __future__ import absolute_import, division, print_function
7
- __metaclass__ = type
6
+ from __future__ import annotations
8
7
 
9
8
 
10
9
  DOCUMENTATION = '''