ansible-core 2.17.6__py3-none-any.whl → 2.18.0__py3-none-any.whl

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

Potentially problematic release.


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

Files changed (325) hide show
  1. ansible/__main__.py +2 -17
  2. ansible/cli/__init__.py +3 -15
  3. ansible/cli/config.py +187 -24
  4. ansible/cli/console.py +1 -1
  5. ansible/cli/doc.py +38 -16
  6. ansible/cli/galaxy.py +3 -49
  7. ansible/cli/inventory.py +2 -2
  8. ansible/cli/pull.py +2 -2
  9. ansible/cli/scripts/ansible_connection_cli_stub.py +1 -10
  10. ansible/config/base.yml +127 -57
  11. ansible/config/manager.py +89 -11
  12. ansible/constants.py +32 -9
  13. ansible/errors/__init__.py +5 -0
  14. ansible/executor/interpreter_discovery.py +1 -1
  15. ansible/executor/play_iterator.py +16 -0
  16. ansible/executor/playbook_executor.py +1 -4
  17. ansible/executor/powershell/become_wrapper.ps1 +4 -5
  18. ansible/executor/powershell/bootstrap_wrapper.ps1 +2 -3
  19. ansible/executor/powershell/exec_wrapper.ps1 +1 -1
  20. ansible/executor/powershell/module_manifest.py +2 -2
  21. ansible/executor/task_executor.py +50 -39
  22. ansible/executor/task_queue_manager.py +1 -1
  23. ansible/executor/task_result.py +1 -1
  24. ansible/galaxy/api.py +3 -4
  25. ansible/galaxy/collection/__init__.py +21 -10
  26. ansible/galaxy/collection/concrete_artifact_manager.py +2 -2
  27. ansible/galaxy/collection/galaxy_api_proxy.py +10 -16
  28. ansible/galaxy/collection/gpg.py +17 -23
  29. ansible/galaxy/data/COPYING +7 -0
  30. ansible/galaxy/data/apb/Dockerfile.j2 +1 -0
  31. ansible/galaxy/data/apb/Makefile.j2 +1 -0
  32. ansible/galaxy/data/apb/README.md +7 -3
  33. ansible/galaxy/data/apb/apb.yml.j2 +1 -0
  34. ansible/galaxy/data/apb/defaults/main.yml.j2 +1 -0
  35. ansible/galaxy/data/apb/handlers/main.yml.j2 +1 -0
  36. ansible/galaxy/data/apb/meta/main.yml.j2 +1 -0
  37. ansible/galaxy/data/apb/playbooks/deprovision.yml.j2 +1 -0
  38. ansible/galaxy/data/apb/playbooks/provision.yml.j2 +1 -0
  39. ansible/galaxy/data/apb/tasks/main.yml.j2 +1 -0
  40. ansible/galaxy/data/apb/tests/ansible.cfg +1 -0
  41. ansible/galaxy/data/apb/tests/inventory +1 -0
  42. ansible/galaxy/data/apb/tests/test.yml.j2 +1 -0
  43. ansible/galaxy/data/apb/vars/main.yml.j2 +1 -0
  44. ansible/galaxy/data/collections_galaxy_meta.yml +1 -0
  45. ansible/galaxy/data/container/defaults/main.yml.j2 +1 -0
  46. ansible/galaxy/data/container/handlers/main.yml.j2 +1 -0
  47. ansible/galaxy/data/container/meta/container.yml.j2 +1 -0
  48. ansible/galaxy/data/container/meta/main.yml.j2 +1 -0
  49. ansible/galaxy/data/container/tasks/main.yml.j2 +1 -0
  50. ansible/galaxy/data/container/tests/ansible.cfg +1 -0
  51. ansible/galaxy/data/container/tests/inventory +1 -0
  52. ansible/galaxy/data/container/tests/test.yml.j2 +1 -0
  53. ansible/galaxy/data/container/vars/main.yml.j2 +1 -0
  54. ansible/galaxy/data/default/collection/README.md.j2 +1 -0
  55. ansible/galaxy/data/default/collection/galaxy.yml.j2 +1 -0
  56. ansible/galaxy/data/default/collection/meta/runtime.yml +1 -0
  57. ansible/galaxy/data/default/collection/plugins/README.md.j2 +1 -0
  58. ansible/galaxy/data/default/role/defaults/main.yml.j2 +1 -0
  59. ansible/galaxy/data/default/role/handlers/main.yml.j2 +1 -0
  60. ansible/galaxy/data/default/role/meta/main.yml.j2 +1 -0
  61. ansible/galaxy/data/default/role/tasks/main.yml.j2 +1 -0
  62. ansible/galaxy/data/default/role/tests/inventory +1 -0
  63. ansible/galaxy/data/default/role/tests/test.yml.j2 +1 -0
  64. ansible/galaxy/data/default/role/vars/main.yml.j2 +1 -0
  65. ansible/galaxy/data/network/cliconf_plugins/example.py.j2 +1 -0
  66. ansible/galaxy/data/network/defaults/main.yml.j2 +1 -0
  67. ansible/galaxy/data/network/library/example_command.py.j2 +1 -0
  68. ansible/galaxy/data/network/library/example_config.py.j2 +1 -0
  69. ansible/galaxy/data/network/library/example_facts.py.j2 +1 -0
  70. ansible/galaxy/data/network/meta/main.yml.j2 +1 -0
  71. ansible/galaxy/data/network/module_utils/example.py.j2 +1 -0
  72. ansible/galaxy/data/network/netconf_plugins/example.py.j2 +1 -0
  73. ansible/galaxy/data/network/tasks/main.yml.j2 +1 -0
  74. ansible/galaxy/data/network/terminal_plugins/example.py.j2 +1 -0
  75. ansible/galaxy/data/network/tests/inventory +1 -0
  76. ansible/galaxy/data/network/tests/test.yml.j2 +1 -0
  77. ansible/galaxy/data/network/vars/main.yml.j2 +1 -0
  78. ansible/galaxy/dependency_resolution/providers.py +3 -3
  79. ansible/galaxy/role.py +1 -1
  80. ansible/galaxy/token.py +20 -8
  81. ansible/keyword_desc.yml +1 -1
  82. ansible/module_utils/_internal/__init__.py +0 -0
  83. ansible/module_utils/_internal/_concurrent/__init__.py +0 -0
  84. ansible/module_utils/_internal/_concurrent/_daemon_threading.py +28 -0
  85. ansible/module_utils/_internal/_concurrent/_futures.py +21 -0
  86. ansible/module_utils/ansible_release.py +2 -2
  87. ansible/module_utils/api.py +2 -2
  88. ansible/module_utils/basic.py +8 -8
  89. ansible/module_utils/common/collections.py +1 -1
  90. ansible/module_utils/common/file.py +0 -6
  91. ansible/module_utils/common/process.py +22 -9
  92. ansible/module_utils/common/text/converters.py +5 -8
  93. ansible/module_utils/common/text/formatters.py +20 -4
  94. ansible/module_utils/common/validation.py +33 -25
  95. ansible/module_utils/compat/paramiko.py +6 -1
  96. ansible/module_utils/compat/selinux.py +2 -2
  97. ansible/module_utils/connection.py +8 -24
  98. ansible/module_utils/csharp/Ansible.Become.cs +14 -25
  99. ansible/module_utils/csharp/Ansible.Process.cs +1 -1
  100. ansible/module_utils/distro/__init__.py +1 -1
  101. ansible/module_utils/distro/_distro.py +8 -4
  102. ansible/module_utils/facts/collector.py +2 -0
  103. ansible/module_utils/facts/default_collectors.py +3 -1
  104. ansible/module_utils/facts/hardware/aix.py +54 -52
  105. ansible/module_utils/facts/hardware/darwin.py +37 -34
  106. ansible/module_utils/facts/hardware/freebsd.py +55 -15
  107. ansible/module_utils/facts/hardware/hpux.py +3 -0
  108. ansible/module_utils/facts/hardware/linux.py +101 -57
  109. ansible/module_utils/facts/hardware/netbsd.py +3 -0
  110. ansible/module_utils/facts/hardware/openbsd.py +4 -1
  111. ansible/module_utils/facts/hardware/sunos.py +7 -1
  112. ansible/module_utils/facts/network/aix.py +16 -17
  113. ansible/module_utils/facts/network/fc_wwn.py +4 -1
  114. ansible/module_utils/facts/network/hpux.py +21 -4
  115. ansible/module_utils/facts/network/iscsi.py +7 -8
  116. ansible/module_utils/facts/network/linux.py +0 -2
  117. ansible/module_utils/facts/other/facter.py +9 -4
  118. ansible/module_utils/facts/other/ohai.py +5 -5
  119. ansible/module_utils/facts/packages.py +49 -7
  120. ansible/module_utils/facts/sysctl.py +33 -31
  121. ansible/module_utils/facts/system/distribution.py +1 -1
  122. ansible/module_utils/facts/system/local.py +12 -22
  123. ansible/module_utils/facts/system/service_mgr.py +3 -1
  124. ansible/module_utils/facts/system/systemd.py +47 -0
  125. ansible/module_utils/powershell/Ansible.ModuleUtils.AddType.psm1 +1 -1
  126. ansible/module_utils/powershell/Ansible.ModuleUtils.CamelConversion.psm1 +1 -1
  127. ansible/module_utils/splitter.py +1 -1
  128. ansible/modules/add_host.py +1 -1
  129. ansible/modules/apt.py +43 -32
  130. ansible/modules/apt_key.py +6 -6
  131. ansible/modules/apt_repository.py +23 -14
  132. ansible/modules/assemble.py +7 -2
  133. ansible/modules/assert.py +4 -4
  134. ansible/modules/blockinfile.py +3 -6
  135. ansible/modules/command.py +1 -1
  136. ansible/modules/copy.py +4 -4
  137. ansible/modules/cron.py +13 -10
  138. ansible/modules/deb822_repository.py +16 -17
  139. ansible/modules/debconf.py +9 -9
  140. ansible/modules/debug.py +1 -1
  141. ansible/modules/dnf.py +79 -164
  142. ansible/modules/dnf5.py +54 -29
  143. ansible/modules/dpkg_selections.py +2 -2
  144. ansible/modules/expect.py +2 -2
  145. ansible/modules/fetch.py +2 -2
  146. ansible/modules/file.py +5 -3
  147. ansible/modules/find.py +40 -12
  148. ansible/modules/gather_facts.py +4 -2
  149. ansible/modules/get_url.py +29 -24
  150. ansible/modules/git.py +35 -35
  151. ansible/modules/group.py +71 -1
  152. ansible/modules/hostname.py +2 -4
  153. ansible/modules/include_vars.py +5 -5
  154. ansible/modules/iptables.py +13 -16
  155. ansible/modules/known_hosts.py +16 -13
  156. ansible/modules/lineinfile.py +1 -4
  157. ansible/modules/meta.py +6 -1
  158. ansible/modules/mount_facts.py +651 -0
  159. ansible/modules/package_facts.py +63 -80
  160. ansible/modules/pause.py +4 -3
  161. ansible/modules/pip.py +14 -14
  162. ansible/modules/replace.py +1 -4
  163. ansible/modules/rpm_key.py +31 -11
  164. ansible/modules/service.py +8 -8
  165. ansible/modules/service_facts.py +20 -5
  166. ansible/modules/set_stats.py +1 -1
  167. ansible/modules/setup.py +3 -3
  168. ansible/modules/stat.py +3 -3
  169. ansible/modules/subversion.py +1 -1
  170. ansible/modules/systemd.py +16 -10
  171. ansible/modules/systemd_service.py +16 -10
  172. ansible/modules/sysvinit.py +4 -4
  173. ansible/modules/unarchive.py +35 -22
  174. ansible/modules/uri.py +24 -18
  175. ansible/modules/user.py +145 -12
  176. ansible/modules/validate_argument_spec.py +3 -3
  177. ansible/modules/wait_for_connection.py +2 -1
  178. ansible/modules/yum_repository.py +136 -179
  179. ansible/parsing/dataloader.py +2 -2
  180. ansible/parsing/mod_args.py +11 -10
  181. ansible/parsing/vault/__init__.py +8 -3
  182. ansible/parsing/yaml/constructor.py +10 -8
  183. ansible/parsing/yaml/objects.py +1 -1
  184. ansible/playbook/base.py +12 -23
  185. ansible/playbook/helpers.py +4 -0
  186. ansible/playbook/loop_control.py +8 -0
  187. ansible/playbook/play.py +4 -22
  188. ansible/playbook/play_context.py +0 -16
  189. ansible/playbook/playbook_include.py +2 -2
  190. ansible/playbook/role/__init__.py +2 -2
  191. ansible/plugins/__init__.py +2 -0
  192. ansible/plugins/action/__init__.py +7 -9
  193. ansible/plugins/action/dnf.py +7 -5
  194. ansible/plugins/action/package.py +5 -4
  195. ansible/plugins/action/reboot.py +2 -2
  196. ansible/plugins/become/__init__.py +1 -1
  197. ansible/plugins/callback/__init__.py +44 -3
  198. ansible/plugins/callback/default.py +1 -1
  199. ansible/plugins/cliconf/__init__.py +1 -1
  200. ansible/plugins/connection/paramiko_ssh.py +2 -80
  201. ansible/plugins/connection/psrp.py +33 -82
  202. ansible/plugins/connection/ssh.py +0 -8
  203. ansible/plugins/connection/winrm.py +46 -1
  204. ansible/plugins/doc_fragments/connection_pipelining.py +2 -2
  205. ansible/plugins/doc_fragments/constructed.py +10 -10
  206. ansible/plugins/doc_fragments/default_callback.py +8 -8
  207. ansible/plugins/doc_fragments/files.py +5 -5
  208. ansible/plugins/doc_fragments/inventory_cache.py +2 -2
  209. ansible/plugins/doc_fragments/result_format_callback.py +6 -6
  210. ansible/plugins/doc_fragments/return_common.py +1 -1
  211. ansible/plugins/doc_fragments/shell_common.py +2 -10
  212. ansible/plugins/doc_fragments/shell_windows.py +0 -9
  213. ansible/plugins/doc_fragments/url.py +2 -2
  214. ansible/plugins/doc_fragments/url_windows.py +4 -5
  215. ansible/plugins/doc_fragments/validate.py +1 -1
  216. ansible/plugins/filter/core.py +2 -0
  217. ansible/plugins/filter/human_to_bytes.yml +9 -0
  218. ansible/plugins/filter/password_hash.yml +1 -1
  219. ansible/plugins/filter/strftime.yml +1 -1
  220. ansible/plugins/filter/to_nice_json.yml +7 -3
  221. ansible/plugins/filter/to_uuid.yml +1 -1
  222. ansible/plugins/inventory/script.py +1 -1
  223. ansible/plugins/list.py +1 -1
  224. ansible/plugins/loader.py +0 -11
  225. ansible/plugins/lookup/config.py +1 -1
  226. ansible/plugins/lookup/csvfile.py +21 -9
  227. ansible/plugins/lookup/env.py +8 -9
  228. ansible/plugins/lookup/ini.py +10 -1
  229. ansible/plugins/lookup/random_choice.py +2 -2
  230. ansible/plugins/lookup/url.py +7 -2
  231. ansible/plugins/shell/__init__.py +15 -20
  232. ansible/plugins/shell/powershell.py +9 -6
  233. ansible/plugins/strategy/__init__.py +16 -7
  234. ansible/plugins/test/core.py +23 -1
  235. ansible/plugins/test/issubset.yml +1 -1
  236. ansible/plugins/test/subset.yml +1 -1
  237. ansible/plugins/test/timedout.yml +20 -0
  238. ansible/plugins/test/vault_encrypted.yml +6 -6
  239. ansible/plugins/test/vaulted_file.yml +19 -0
  240. ansible/release.py +2 -2
  241. ansible/template/__init__.py +3 -8
  242. ansible/utils/collection_loader/_collection_finder.py +23 -55
  243. ansible/utils/display.py +44 -31
  244. ansible/utils/jsonrpc.py +1 -1
  245. ansible/utils/listify.py +1 -5
  246. ansible/utils/path.py +3 -0
  247. ansible/utils/vars.py +18 -27
  248. ansible/vars/manager.py +7 -150
  249. ansible/vars/plugins.py +1 -1
  250. ansible_core-2.18.0.dist-info/Apache-License.txt +202 -0
  251. {ansible_core-2.17.6.dist-info → ansible_core-2.18.0.dist-info}/METADATA +36 -23
  252. ansible_core-2.18.0.dist-info/MIT-license.txt +14 -0
  253. ansible_core-2.18.0.dist-info/PSF-license.txt +48 -0
  254. {ansible_core-2.17.6.dist-info → ansible_core-2.18.0.dist-info}/RECORD +316 -311
  255. {ansible_core-2.17.6.dist-info → ansible_core-2.18.0.dist-info}/entry_points.txt +1 -1
  256. ansible_core-2.18.0.dist-info/simplified_bsd.txt +8 -0
  257. ansible_test/_data/completion/docker.txt +7 -7
  258. ansible_test/_data/completion/remote.txt +5 -4
  259. ansible_test/_data/completion/windows.txt +4 -4
  260. ansible_test/_data/requirements/ansible-test.txt +1 -2
  261. ansible_test/_data/requirements/constraints.txt +1 -2
  262. ansible_test/_data/requirements/sanity.ansible-doc.txt +3 -3
  263. ansible_test/_data/requirements/sanity.changelog.in +1 -1
  264. ansible_test/_data/requirements/sanity.changelog.txt +4 -4
  265. ansible_test/_data/requirements/sanity.import.plugin.txt +2 -2
  266. ansible_test/_data/requirements/sanity.import.txt +1 -1
  267. ansible_test/_data/requirements/sanity.integration-aliases.txt +1 -1
  268. ansible_test/_data/requirements/sanity.pep8.txt +1 -1
  269. ansible_test/_data/requirements/sanity.pylint.txt +6 -8
  270. ansible_test/_data/requirements/sanity.runtime-metadata.txt +2 -2
  271. ansible_test/_data/requirements/sanity.validate-modules.txt +3 -3
  272. ansible_test/_data/requirements/sanity.yamllint.in +1 -0
  273. ansible_test/_data/requirements/sanity.yamllint.txt +1 -1
  274. ansible_test/_internal/ansible_util.py +8 -35
  275. ansible_test/_internal/ci/azp.py +1 -1
  276. ansible_test/_internal/classification/__init__.py +0 -2
  277. ansible_test/_internal/cli/parsers/key_value_parsers.py +3 -0
  278. ansible_test/_internal/commands/integration/cloud/hcloud.py +1 -1
  279. ansible_test/_internal/commands/integration/cloud/httptester.py +1 -1
  280. ansible_test/_internal/commands/integration/cloud/nios.py +1 -1
  281. ansible_test/_internal/commands/sanity/__init__.py +96 -19
  282. ansible_test/_internal/commands/sanity/pylint.py +20 -24
  283. ansible_test/_internal/completion.py +2 -0
  284. ansible_test/_internal/constants.py +0 -1
  285. ansible_test/_internal/coverage_util.py +1 -2
  286. ansible_test/_internal/docker_util.py +1 -1
  287. ansible_test/_internal/encoding.py +4 -4
  288. ansible_test/_internal/host_configs.py +10 -0
  289. ansible_test/_internal/host_profiles.py +9 -13
  290. ansible_test/_internal/pypi_proxy.py +1 -1
  291. ansible_test/_internal/python_requirements.py +5 -14
  292. ansible_test/_internal/timeout.py +1 -1
  293. ansible_test/_internal/util.py +40 -0
  294. ansible_test/_internal/util_common.py +5 -1
  295. ansible_test/_util/controller/sanity/code-smell/action-plugin-docs.json +3 -1
  296. ansible_test/_util/controller/sanity/code-smell/action-plugin-docs.py +6 -3
  297. ansible_test/_util/controller/sanity/code-smell/empty-init.json +0 -2
  298. ansible_test/_util/controller/sanity/pylint/config/ansible-test-target.cfg +5 -0
  299. ansible_test/_util/controller/sanity/pylint/config/ansible-test.cfg +5 -0
  300. ansible_test/_util/controller/sanity/pylint/config/code-smell.cfg +5 -0
  301. ansible_test/_util/controller/sanity/pylint/config/collection.cfg +6 -0
  302. ansible_test/_util/controller/sanity/pylint/config/default.cfg +6 -0
  303. ansible_test/_util/controller/sanity/pylint/plugins/deprecated.py +1 -19
  304. ansible_test/_util/controller/sanity/shellcheck/exclude.txt +1 -0
  305. ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py +67 -2
  306. ansible_test/_util/controller/sanity/validate-modules/validate_modules/schema.py +27 -5
  307. ansible_test/_util/target/cli/ansible_test_cli_stub.py +0 -0
  308. ansible_test/_util/target/common/constants.py +2 -2
  309. ansible_test/_util/target/injector/python.py +5 -0
  310. ansible_test/_util/target/pytest/plugins/ansible_pytest_coverage.py +6 -0
  311. ansible_test/_util/target/sanity/import/importer.py +1 -1
  312. ansible_test/_util/target/setup/bootstrap.sh +6 -17
  313. ansible_test/_util/target/setup/requirements.py +18 -24
  314. ansible_test/config/config.yml +1 -1
  315. ansible_core-2.17.6.data/scripts/ansible-test +0 -44
  316. ansible_test/_data/requirements/sanity.mypy.in +0 -10
  317. ansible_test/_data/requirements/sanity.mypy.txt +0 -18
  318. ansible_test/_internal/commands/sanity/mypy.py +0 -274
  319. ansible_test/_util/controller/sanity/mypy/ansible-core.ini +0 -116
  320. ansible_test/_util/controller/sanity/mypy/ansible-test.ini +0 -27
  321. ansible_test/_util/controller/sanity/mypy/modules.ini +0 -92
  322. ansible_test/_util/controller/sanity/mypy/packaging.ini +0 -20
  323. {ansible_core-2.17.6.dist-info → ansible_core-2.18.0.dist-info}/COPYING +0 -0
  324. {ansible_core-2.17.6.dist-info → ansible_core-2.18.0.dist-info}/WHEEL +0 -0
  325. {ansible_core-2.17.6.dist-info → ansible_core-2.18.0.dist-info}/top_level.txt +0 -0
@@ -3,24 +3,29 @@
3
3
 
4
4
  from __future__ import annotations
5
5
 
6
+ import ansible.module_utils.compat.typing as t
7
+
6
8
  from abc import ABCMeta, abstractmethod
7
9
 
8
10
  from ansible.module_utils.six import with_metaclass
11
+ from ansible.module_utils.basic import missing_required_lib
9
12
  from ansible.module_utils.common.process import get_bin_path
13
+ from ansible.module_utils.common.respawn import has_respawned, probe_interpreters_for_module, respawn_module
10
14
  from ansible.module_utils.common._utils import get_all_subclasses
11
15
 
12
16
 
13
17
  def get_all_pkg_managers():
14
18
 
15
- return {obj.__name__.lower(): obj for obj in get_all_subclasses(PkgMgr) if obj not in (CLIMgr, LibMgr)}
19
+ return {obj.__name__.lower(): obj for obj in get_all_subclasses(PkgMgr) if obj not in (CLIMgr, LibMgr, RespawningLibMgr)}
16
20
 
17
21
 
18
22
  class PkgMgr(with_metaclass(ABCMeta, object)): # type: ignore[misc]
19
23
 
20
24
  @abstractmethod
21
- def is_available(self):
25
+ def is_available(self, handle_exceptions):
22
26
  # This method is supposed to return True/False if the package manager is currently installed/usable
23
27
  # It can also 'prep' the required systems in the process of detecting availability
28
+ # If handle_exceptions is false it should raise exceptions related to manager discovery instead of handling them.
24
29
  pass
25
30
 
26
31
  @abstractmethod
@@ -58,16 +63,50 @@ class LibMgr(PkgMgr):
58
63
  self._lib = None
59
64
  super(LibMgr, self).__init__()
60
65
 
61
- def is_available(self):
66
+ def is_available(self, handle_exceptions=True):
62
67
  found = False
63
68
  try:
64
69
  self._lib = __import__(self.LIB)
65
70
  found = True
66
71
  except ImportError:
67
- pass
72
+ if not handle_exceptions:
73
+ raise Exception(missing_required_lib(self.LIB))
68
74
  return found
69
75
 
70
76
 
77
+ class RespawningLibMgr(LibMgr):
78
+
79
+ CLI_BINARIES = [] # type: t.List[str]
80
+ INTERPRETERS = ['/usr/bin/python3']
81
+
82
+ def is_available(self, handle_exceptions=True):
83
+ if super(RespawningLibMgr, self).is_available():
84
+ return True
85
+
86
+ for binary in self.CLI_BINARIES:
87
+ try:
88
+ bin_path = get_bin_path(binary)
89
+ except ValueError:
90
+ # Not an interesting exception to raise, just a speculative probe
91
+ continue
92
+ else:
93
+ # It looks like this package manager is installed
94
+ if not has_respawned():
95
+ # See if respawning will help
96
+ interpreter_path = probe_interpreters_for_module(self.INTERPRETERS, self.LIB)
97
+ if interpreter_path:
98
+ respawn_module(interpreter_path)
99
+ # The module will exit when the respawned copy completes
100
+
101
+ if not handle_exceptions:
102
+ raise Exception(f'Found executable at {bin_path}. {missing_required_lib(self.LIB)}')
103
+
104
+ if not handle_exceptions:
105
+ raise Exception(missing_required_lib(self.LIB))
106
+
107
+ return False
108
+
109
+
71
110
  class CLIMgr(PkgMgr):
72
111
 
73
112
  CLI = None # type: str | None
@@ -77,9 +116,12 @@ class CLIMgr(PkgMgr):
77
116
  self._cli = None
78
117
  super(CLIMgr, self).__init__()
79
118
 
80
- def is_available(self):
119
+ def is_available(self, handle_exceptions=True):
120
+ found = False
81
121
  try:
82
122
  self._cli = get_bin_path(self.CLI)
123
+ found = True
83
124
  except ValueError:
84
- return False
85
- return True
125
+ if not handle_exceptions:
126
+ raise
127
+ return found
@@ -21,41 +21,43 @@ from ansible.module_utils.common.text.converters import to_text
21
21
 
22
22
 
23
23
  def get_sysctl(module, prefixes):
24
- sysctl_cmd = module.get_bin_path('sysctl')
25
- cmd = [sysctl_cmd]
26
- cmd.extend(prefixes)
27
24
 
28
25
  sysctl = dict()
29
-
30
- try:
31
- rc, out, err = module.run_command(cmd)
32
- except (IOError, OSError) as e:
33
- module.warn('Unable to read sysctl: %s' % to_text(e))
34
- rc = 1
35
-
36
- if rc == 0:
37
- key = ''
38
- value = ''
39
- for line in out.splitlines():
40
- if not line.strip():
41
- continue
42
-
43
- if line.startswith(' '):
44
- # handle multiline values, they will not have a starting key
45
- # Add the newline back in so people can split on it to parse
46
- # lines if they need to.
47
- value += '\n' + line
48
- continue
26
+ sysctl_cmd = module.get_bin_path('sysctl')
27
+ if sysctl_cmd is not None:
28
+
29
+ cmd = [sysctl_cmd]
30
+ cmd.extend(prefixes)
31
+
32
+ try:
33
+ rc, out, err = module.run_command(cmd)
34
+ except (IOError, OSError) as e:
35
+ module.warn('Unable to read sysctl: %s' % to_text(e))
36
+ rc = 1
37
+
38
+ if rc == 0:
39
+ key = ''
40
+ value = ''
41
+ for line in out.splitlines():
42
+ if not line.strip():
43
+ continue
44
+
45
+ if line.startswith(' '):
46
+ # handle multiline values, they will not have a starting key
47
+ # Add the newline back in so people can split on it to parse
48
+ # lines if they need to.
49
+ value += '\n' + line
50
+ continue
51
+
52
+ if key:
53
+ sysctl[key] = value.strip()
54
+
55
+ try:
56
+ (key, value) = re.split(r'\s?=\s?|: ', line, maxsplit=1)
57
+ except Exception as e:
58
+ module.warn('Unable to split sysctl line (%s): %s' % (to_text(line), to_text(e)))
49
59
 
50
60
  if key:
51
61
  sysctl[key] = value.strip()
52
62
 
53
- try:
54
- (key, value) = re.split(r'\s?=\s?|: ', line, maxsplit=1)
55
- except Exception as e:
56
- module.warn('Unable to split sysctl line (%s): %s' % (to_text(line), to_text(e)))
57
-
58
- if key:
59
- sysctl[key] = value.strip()
60
-
61
63
  return sysctl
@@ -517,7 +517,7 @@ class Distribution(object):
517
517
  'Linux Mint', 'SteamOS', 'Devuan', 'Kali', 'Cumulus Linux',
518
518
  'Pop!_OS', 'Parrot', 'Pardus GNU/Linux', 'Uos', 'Deepin', 'OSMC'],
519
519
  'Suse': ['SuSE', 'SLES', 'SLED', 'openSUSE', 'openSUSE Tumbleweed',
520
- 'SLES_SAP', 'SUSE_LINUX', 'openSUSE Leap', 'ALP-Dolomite'],
520
+ 'SLES_SAP', 'SUSE_LINUX', 'openSUSE Leap', 'ALP-Dolomite', 'SL-Micro'],
521
521
  'Archlinux': ['Archlinux', 'Antergos', 'Manjaro'],
522
522
  'Mandrake': ['Mandrake', 'Mandriva'],
523
523
  'Solaris': ['Solaris', 'Nexenta', 'OmniOS', 'OpenIndiana', 'SmartOS'],
@@ -1,17 +1,5 @@
1
- # This file is part of Ansible
2
- #
3
- # Ansible is free software: you can redistribute it and/or modify
4
- # it under the terms of the GNU General Public License as published by
5
- # the Free Software Foundation, either version 3 of the License, or
6
- # (at your option) any later version.
7
- #
8
- # Ansible is distributed in the hope that it will be useful,
9
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
- # GNU General Public License for more details.
12
- #
13
- # You should have received a copy of the GNU General Public License
14
- # along with Ansible. If not, see <http://www.gnu.org/licenses/>.
1
+ # Copyright: Contributors to the Ansible project
2
+ # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
15
3
 
16
4
  from __future__ import annotations
17
5
 
@@ -25,7 +13,6 @@ import ansible.module_utils.compat.typing as t
25
13
  from ansible.module_utils.common.text.converters import to_text
26
14
  from ansible.module_utils.facts.utils import get_file_content
27
15
  from ansible.module_utils.facts.collector import BaseFactCollector
28
- from ansible.module_utils.six import PY3
29
16
  from ansible.module_utils.six.moves import configparser, StringIO
30
17
 
31
18
 
@@ -91,12 +78,9 @@ class LocalFactCollector(BaseFactCollector):
91
78
  # if that fails read it with ConfigParser
92
79
  cp = configparser.ConfigParser()
93
80
  try:
94
- if PY3:
95
- cp.read_file(StringIO(out))
96
- else:
97
- cp.readfp(StringIO(out))
81
+ cp.read_file(StringIO(out))
98
82
  except configparser.Error:
99
- fact = "error loading facts as JSON or ini - please check content: %s" % fn
83
+ fact = f"error loading facts as JSON or ini - please check content: {fn}"
100
84
  module.warn(fact)
101
85
  else:
102
86
  fact = {}
@@ -104,8 +88,14 @@ class LocalFactCollector(BaseFactCollector):
104
88
  if sect not in fact:
105
89
  fact[sect] = {}
106
90
  for opt in cp.options(sect):
107
- val = cp.get(sect, opt)
108
- fact[sect][opt] = val
91
+ try:
92
+ val = cp.get(sect, opt)
93
+ except configparser.Error as ex:
94
+ fact = f"error loading facts as ini - please check content: {fn} ({ex})"
95
+ module.warn(fact)
96
+ continue
97
+ else:
98
+ fact[sect][opt] = val
109
99
  except Exception as e:
110
100
  fact = "Failed to convert (%s) to JSON: %s" % (fn, to_text(e))
111
101
  module.warn(fact)
@@ -106,7 +106,7 @@ class ServiceMgrFactCollector(BaseFactCollector):
106
106
  proc_1 = proc_1.strip()
107
107
 
108
108
  if proc_1 is not None and (proc_1 == 'init' or proc_1.endswith('sh')):
109
- # many systems return init, so this cannot be trusted, if it ends in 'sh' it probalby is a shell in a container
109
+ # many systems return init, so this cannot be trusted, if it ends in 'sh' it probably is a shell in a container
110
110
  proc_1 = None
111
111
 
112
112
  # if not init/None it should be an identifiable or custom init, so we are done!
@@ -144,6 +144,8 @@ class ServiceMgrFactCollector(BaseFactCollector):
144
144
  service_mgr_name = 'systemd'
145
145
  elif os.path.exists('/etc/init.d/'):
146
146
  service_mgr_name = 'sysvinit'
147
+ elif os.path.exists('/etc/dinit.d/'):
148
+ service_mgr_name = 'dinit'
147
149
 
148
150
  if not service_mgr_name:
149
151
  # if we cannot detect, fallback to generic 'service'
@@ -0,0 +1,47 @@
1
+ # Get systemd version and features
2
+ #
3
+ # This file is part of Ansible
4
+ #
5
+ # Ansible is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # Ansible is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with Ansible. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ from __future__ import annotations
19
+
20
+ import ansible.module_utils.compat.typing as t
21
+
22
+ from ansible.module_utils.facts.collector import BaseFactCollector
23
+ from ansible.module_utils.facts.system.service_mgr import ServiceMgrFactCollector
24
+
25
+
26
+ class SystemdFactCollector(BaseFactCollector):
27
+ name = "systemd"
28
+ _fact_ids = set() # type: t.Set[str]
29
+
30
+ def collect(self, module=None, collected_facts=None):
31
+ systemctl_bin = module.get_bin_path("systemctl")
32
+ systemd_facts = {}
33
+ if systemctl_bin and ServiceMgrFactCollector.is_systemd_managed(module):
34
+ rc, stdout, dummy = module.run_command(
35
+ [systemctl_bin, "--version"],
36
+ check_rc=False,
37
+ )
38
+
39
+ if rc != 0:
40
+ return systemd_facts
41
+
42
+ systemd_facts["systemd"] = {
43
+ "features": str(stdout.split("\n")[1]),
44
+ "version": int(stdout.split(" ")[1]),
45
+ }
46
+
47
+ return systemd_facts
@@ -37,7 +37,7 @@ Function Add-CSharpType {
37
37
  .PARAMETER CompileSymbols
38
38
  [String[]] A list of symbols to be defined during compile time. These are
39
39
  added to the existing symbols, 'CORECLR', 'WINDOWS', 'UNIX' that are set
40
- conditionalls in this cmdlet.
40
+ conditionals in this cmdlet.
41
41
 
42
42
  .NOTES
43
43
  The following features were added to control the compiling options from the
@@ -4,7 +4,7 @@
4
4
  # used by Convert-DictToSnakeCase to convert a string in camelCase
5
5
  # format to snake_case
6
6
  Function Convert-StringToSnakeCase($string) {
7
- # cope with pluralized abbreaviations such as TargetGroupARNs
7
+ # cope with pluralized abbreviations such as TargetGroupARNs
8
8
  if ($string -cmatch "[A-Z]{3,}s") {
9
9
  $replacement_string = $string -creplace $matches[0], "_$($matches[0].ToLower())"
10
10
 
@@ -81,7 +81,7 @@ def split_args(args):
81
81
  '''
82
82
 
83
83
  # the list of params parsed out of the arg string
84
- # this is going to be the result value when we are donei
84
+ # this is going to be the result value when we are done
85
85
  params = []
86
86
 
87
87
  # here we encode the args, so we have a uniform charset to
@@ -61,7 +61,7 @@ notes:
61
61
  - The alias O(host) of the parameter O(name) is only available on Ansible 2.4 and newer.
62
62
  - Since Ansible 2.4, the C(inventory_dir) variable is now set to V(None) instead of the 'global inventory source',
63
63
  because you can now have multiple sources. An example was added that shows how to partially restore the previous behaviour.
64
- - Though this module does not change the remote host, we do provide 'changed' status as it can be useful for those trying to track inventory changes.
64
+ - Though this module does not change the remote host, we do provide C(changed) status as it can be useful for those trying to track inventory changes.
65
65
  - The hosts added will not bypass the C(--limit) from the command line, so both of those need to be in agreement to make them available as play targets.
66
66
  They are still available from hostvars and for delegation as a normal part of the inventory.
67
67
  seealso:
ansible/modules/apt.py CHANGED
@@ -21,6 +21,7 @@ options:
21
21
  description:
22
22
  - A list of package names, like V(foo), or package specifier with version, like V(foo=1.0) or V(foo>=1.0).
23
23
  Name wildcards (fnmatch) like V(apt*) and version wildcards like V(foo=1.0*) are also supported.
24
+ - Do not use single or double quotes around the version when referring to the package name with a specific version, such as V(foo=1.0) or V(foo>=1.0).
24
25
  aliases: [ package, pkg ]
25
26
  type: list
26
27
  elements: str
@@ -62,21 +63,20 @@ options:
62
63
  default: 'no'
63
64
  default_release:
64
65
  description:
65
- - Corresponds to the C(-t) option for I(apt) and sets pin priorities
66
+ - Corresponds to the C(-t) option for I(apt) and sets pin priorities.
66
67
  aliases: [ default-release ]
67
68
  type: str
68
69
  install_recommends:
69
70
  description:
70
- - Corresponds to the C(--no-install-recommends) option for I(apt). V(true) installs recommended packages. V(false) does not install
71
+ - Corresponds to the C(--no-install-recommends) option for C(apt). V(true) installs recommended packages. V(false) does not install
71
72
  recommended packages. By default, Ansible will use the same defaults as the operating system. Suggested packages are never installed.
72
73
  aliases: [ install-recommends ]
73
74
  type: bool
74
75
  force:
75
76
  description:
76
- - 'Corresponds to the C(--force-yes) to I(apt-get) and implies O(allow_unauthenticated=yes) and O(allow_downgrade=yes)'
77
- - "This option will disable checking both the packages' signatures and the certificates of the
78
- web servers they are downloaded from."
79
- - 'This option *is not* the equivalent of passing the C(-f) flag to I(apt-get) on the command line'
77
+ - 'Corresponds to the C(--force-yes) to C(apt-get) and implies O(allow_unauthenticated=yes) and O(allow_downgrade=yes).'
78
+ - "This option will disable checking both the packages' signatures and the certificates of the web servers they are downloaded from."
79
+ - 'This option *is not* the equivalent of passing the C(-f) flag to C(apt-get) on the command line.'
80
80
  - '**This is a destructive operation with the potential to destroy your system, and it should almost never be used.**
81
81
  Please also see C(man apt-get) for more information.'
82
82
  type: bool
@@ -84,7 +84,7 @@ options:
84
84
  clean:
85
85
  description:
86
86
  - Run the equivalent of C(apt-get clean) to clear out the local repository of retrieved package files. It removes everything but
87
- the lock file from /var/cache/apt/archives/ and /var/cache/apt/archives/partial/.
87
+ the lock file from C(/var/cache/apt/archives/) and C(/var/cache/apt/archives/partial/).
88
88
  - Can be run as part of the package installation (clean runs before install) or as a separate step.
89
89
  type: bool
90
90
  default: 'no'
@@ -92,7 +92,7 @@ options:
92
92
  allow_unauthenticated:
93
93
  description:
94
94
  - Ignore if packages cannot be authenticated. This is useful for bootstrapping environments that manage their own apt-key setup.
95
- - 'O(allow_unauthenticated) is only supported with O(state): V(install)/V(present)'
95
+ - 'O(allow_unauthenticated) is only supported with O(state): V(install)/V(present).'
96
96
  aliases: [ allow-unauthenticated ]
97
97
  type: bool
98
98
  default: 'no'
@@ -110,7 +110,7 @@ options:
110
110
  version_added: "2.12"
111
111
  allow_change_held_packages:
112
112
  description:
113
- - Allows changing the version of a package which is on the apt hold list
113
+ - Allows changing the version of a package which is on the apt hold list.
114
114
  type: bool
115
115
  default: 'no'
116
116
  version_added: '2.13'
@@ -127,14 +127,14 @@ options:
127
127
  type: str
128
128
  dpkg_options:
129
129
  description:
130
- - Add dpkg options to apt command. Defaults to '-o "Dpkg::Options::=--force-confdef" -o "Dpkg::Options::=--force-confold"'
131
- - Options should be supplied as comma separated list
130
+ - Add C(dpkg) options to C(apt) command. Defaults to C(-o "Dpkg::Options::=--force-confdef" -o "Dpkg::Options::=--force-confold").
131
+ - Options should be supplied as comma separated list.
132
132
  default: force-confdef,force-confold
133
133
  type: str
134
134
  deb:
135
135
  description:
136
136
  - Path to a .deb package on the remote machine.
137
- - If :// in the path, ansible will attempt to download deb before installing. (Version added 2.1)
137
+ - If C(://) in the path, ansible will attempt to download deb before installing. (Version added 2.1)
138
138
  - Requires the C(xz-utils) package to extract the control file of the deb package to install.
139
139
  type: path
140
140
  required: false
@@ -142,7 +142,8 @@ options:
142
142
  autoremove:
143
143
  description:
144
144
  - If V(true), remove unused dependency packages for all module states except V(build-dep). It can also be used as the only option.
145
- - Previous to version 2.4, autoclean was also an alias for autoremove, now it is its own separate command. See documentation for further information.
145
+ - Previous to version 2.4, O(autoclean) was also an alias for O(autoremove), now it is its own separate command.
146
+ See documentation for further information.
146
147
  type: bool
147
148
  default: 'no'
148
149
  version_added: "2.1"
@@ -154,10 +155,10 @@ options:
154
155
  version_added: "2.4"
155
156
  policy_rc_d:
156
157
  description:
157
- - Force the exit code of /usr/sbin/policy-rc.d.
158
- - For example, if I(policy_rc_d=101) the installed package will not trigger a service start.
159
- - If /usr/sbin/policy-rc.d already exists, it is backed up and restored after the package installation.
160
- - If V(null), the /usr/sbin/policy-rc.d isn't created/changed.
158
+ - Force the exit code of C(/usr/sbin/policy-rc.d).
159
+ - For example, if O(policy_rc_d=101) the installed package will not trigger a service start.
160
+ - If C(/usr/sbin/policy-rc.d) already exists, it is backed up and restored after the package installation.
161
+ - If V(null), the C(/usr/sbin/policy-rc.d) is not created/changed.
161
162
  type: int
162
163
  default: null
163
164
  version_added: "2.8"
@@ -178,7 +179,7 @@ options:
178
179
  version_added: "2.11"
179
180
  force_apt_get:
180
181
  description:
181
- - Force usage of apt-get instead of aptitude
182
+ - Force usage of apt-get instead of aptitude.
182
183
  type: bool
183
184
  default: 'no'
184
185
  version_added: "2.4"
@@ -204,22 +205,22 @@ attributes:
204
205
  platforms: debian
205
206
  notes:
206
207
  - Three of the upgrade modes (V(full), V(safe) and its alias V(true)) required C(aptitude) up to 2.3, since 2.4 C(apt-get) is used as a fall-back.
207
- - In most cases, packages installed with apt will start newly installed services by default. Most distributions have mechanisms to avoid this.
208
+ - In most cases, packages installed with I(apt) will start newly installed services by default. Most distributions have mechanisms to avoid this.
208
209
  For example when installing Postgresql-9.5 in Debian 9, creating an executable shell script (/usr/sbin/policy-rc.d) that throws
209
- a return code of 101 will stop Postgresql 9.5 starting up after install. Remove the file or its execute permission afterward.
210
- - The apt-get commandline supports implicit regex matches here but we do not because it can let typos through easier
210
+ a return code of 101 will stop Postgresql 9.5 starting up after install. Remove the file or its execute permission afterward.
211
+ - The C(apt-get) commandline supports implicit regex matches here but we do not because it can let typos through easier
211
212
  (If you typo C(foo) as C(fo) apt-get would install packages that have "fo" in their name with a warning and a prompt for the user.
212
- Since we don't have warnings and prompts before installing, we disallow this.Use an explicit fnmatch pattern if you want wildcarding)
213
+ Since there are no warnings and prompts before installing, we disallow this. Use an explicit fnmatch pattern if you want wildcarding).
213
214
  - When used with a C(loop:) each package will be processed individually, it is much more efficient to pass the list directly to the O(name) option.
214
215
  - When O(default_release) is used, an implicit priority of 990 is used. This is the same behavior as C(apt-get -t).
215
216
  - When an exact version is specified, an implicit priority of 1001 is used.
216
- - If the interpreter can't import ``python-apt``/``python3-apt`` the module will check for it in system-owned interpreters as well.
217
+ - If the interpreter can't import C(python-apt)/C(python3-apt) the module will check for it in system-owned interpreters as well.
217
218
  If the dependency can't be found, the module will attempt to install it.
218
219
  If the dependency is found or installed, the module will be respawned under the correct interpreter.
219
220
  '''
220
221
 
221
222
  EXAMPLES = '''
222
- - name: Install apache httpd (state=present is optional)
223
+ - name: Install apache httpd (state=present is optional)
223
224
  ansible.builtin.apt:
224
225
  name: apache2
225
226
  state: present
@@ -364,8 +365,8 @@ import datetime
364
365
  import fnmatch
365
366
  import locale as locale_module
366
367
  import os
367
- import random
368
368
  import re
369
+ import secrets
369
370
  import shutil
370
371
  import sys
371
372
  import tempfile
@@ -380,8 +381,8 @@ from ansible.module_utils.six import string_types
380
381
  from ansible.module_utils.urls import fetch_file
381
382
 
382
383
  DPKG_OPTIONS = 'force-confdef,force-confold'
383
- APT_GET_ZERO = "\n0 upgraded, 0 newly installed"
384
- APTITUDE_ZERO = "\n0 packages upgraded, 0 newly installed"
384
+ APT_GET_ZERO = "\n0 upgraded, 0 newly installed, 0 to remove"
385
+ APTITUDE_ZERO = "\n0 packages upgraded, 0 newly installed, 0 to remove"
385
386
  APT_LISTS_PATH = "/var/lib/apt/lists"
386
387
  APT_UPDATE_SUCCESS_STAMP_PATH = "/var/lib/apt/periodic/update-success-stamp"
387
388
  APT_MARK_INVALID_OP = 'Invalid operation'
@@ -506,7 +507,7 @@ def package_best_match(pkgname, version_cmp, version, release, cache):
506
507
  policy.create_pin('Release', pkgname, release, 990)
507
508
  if version_cmp == "=":
508
509
  # Installing a specific version from command line overrides all pinning
509
- # We don't mimmic this exactly, but instead set a priority which is higher than all APT built-in pin priorities.
510
+ # We don't mimic this exactly, but instead set a priority which is higher than all APT built-in pin priorities.
510
511
  policy.create_pin('Version', pkgname, version, 1001)
511
512
  pkg = cache[pkgname]
512
513
  pkgver = policy.get_candidate_ver(pkg)
@@ -1251,6 +1252,7 @@ def main():
1251
1252
  LC_ALL=locale,
1252
1253
  LC_MESSAGES=locale,
1253
1254
  LC_CTYPE=locale,
1255
+ LANGUAGE=locale,
1254
1256
  )
1255
1257
  module.run_command_environ_update = APT_ENV_VARS
1256
1258
 
@@ -1386,23 +1388,32 @@ def main():
1386
1388
  err = ''
1387
1389
  update_cache_retries = module.params.get('update_cache_retries')
1388
1390
  update_cache_retry_max_delay = module.params.get('update_cache_retry_max_delay')
1389
- randomize = random.randint(0, 1000) / 1000.0
1391
+ randomize = secrets.randbelow(1000) / 1000.0
1390
1392
 
1391
1393
  for retry in range(update_cache_retries):
1392
1394
  try:
1393
1395
  if not module.check_mode:
1394
1396
  cache.update()
1395
1397
  break
1396
- except apt.cache.FetchFailedException as e:
1397
- err = to_native(e)
1398
+ except apt.cache.FetchFailedException as fetch_failed_exc:
1399
+ err = fetch_failed_exc
1400
+ module.warn(
1401
+ f"Failed to update cache after {retry + 1} retries due "
1402
+ f"to {to_native(fetch_failed_exc)}, retrying"
1403
+ )
1398
1404
 
1399
1405
  # Use exponential backoff plus a little bit of randomness
1400
1406
  delay = 2 ** retry + randomize
1401
1407
  if delay > update_cache_retry_max_delay:
1402
1408
  delay = update_cache_retry_max_delay + randomize
1403
1409
  time.sleep(delay)
1410
+ module.warn(f"Sleeping for {int(round(delay))} seconds, before attempting to refresh the cache again")
1404
1411
  else:
1405
- module.fail_json(msg='Failed to update apt cache: %s' % (err if err else 'unknown reason'))
1412
+ msg = (
1413
+ f"Failed to update apt cache after {update_cache_retries} retries: "
1414
+ f"{err if err else 'unknown reason'}"
1415
+ )
1416
+ module.fail_json(msg=msg)
1406
1417
 
1407
1418
  cache.open(progress=None)
1408
1419
  mtimestamp, post_cache_update_time = get_updated_cache_time()
@@ -26,13 +26,13 @@ attributes:
26
26
  platform:
27
27
  platforms: debian
28
28
  notes:
29
- - The apt-key command used by this module has been deprecated. See the L(Debian wiki,https://wiki.debian.org/DebianRepository/UseThirdParty) for details.
30
- This module is kept for backwards compatibility for systems that still use apt-key as the main way to manage apt repository keys.
29
+ - The C(apt-key) command used by this module has been deprecated. See the L(Debian wiki,https://wiki.debian.org/DebianRepository/UseThirdParty) for details.
30
+ This module is kept for backwards compatibility for systems that still use C(apt-key) as the main way to manage apt repository keys.
31
31
  - As a sanity check, downloaded key id must match the one specified.
32
32
  - "Use full fingerprint (40 characters) key ids to avoid key collisions.
33
33
  To generate a full-fingerprint imported key: C(apt-key adv --list-public-keys --with-fingerprint --with-colons)."
34
- - If you specify both the key id and the URL with O(state=present), the task can verify or add the key as needed.
35
- - Adding a new key requires an apt cache update (e.g. using the M(ansible.builtin.apt) module's update_cache option).
34
+ - If you specify both the key O(id) and the O(url) with O(state=present), the task can verify or add the key as needed.
35
+ - Adding a new key requires an apt cache update (e.g. using the M(ansible.builtin.apt) module's C(update_cache) option).
36
36
  requirements:
37
37
  - gpg
38
38
  seealso:
@@ -42,7 +42,7 @@ options:
42
42
  description:
43
43
  - The identifier of the key.
44
44
  - Including this allows check mode to correctly report the changed state.
45
- - If specifying a subkey's id be aware that apt-key does not understand how to remove keys via a subkey id. Specify the primary key's id instead.
45
+ - If specifying a subkey's id be aware that apt-key does not understand how to remove keys via a subkey id. Specify the primary key's id instead.
46
46
  - This parameter is required when O(state) is set to V(absent).
47
47
  type: str
48
48
  data:
@@ -188,7 +188,7 @@ def lang_env(module):
188
188
 
189
189
  if not hasattr(lang_env, 'result'):
190
190
  locale = get_best_parsable_locale(module)
191
- lang_env.result = dict(LANG=locale, LC_ALL=locale, LC_MESSAGES=locale)
191
+ lang_env.result = dict(LANG=locale, LC_ALL=locale, LC_MESSAGES=locale, LANGUAGE=locale)
192
192
 
193
193
  return lang_env.result
194
194