ansible-core 2.17.5rc1__py3-none-any.whl → 2.18.0rc1__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 (330) 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 +34 -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 +10 -5
  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 +2 -2
  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/facts/timeout.py +1 -1
  126. ansible/module_utils/powershell/Ansible.ModuleUtils.AddType.psm1 +1 -1
  127. ansible/module_utils/powershell/Ansible.ModuleUtils.CamelConversion.psm1 +1 -1
  128. ansible/module_utils/splitter.py +1 -1
  129. ansible/modules/add_host.py +1 -1
  130. ansible/modules/apt.py +43 -32
  131. ansible/modules/apt_key.py +6 -6
  132. ansible/modules/apt_repository.py +23 -14
  133. ansible/modules/assemble.py +7 -2
  134. ansible/modules/assert.py +4 -4
  135. ansible/modules/blockinfile.py +3 -6
  136. ansible/modules/command.py +1 -1
  137. ansible/modules/copy.py +4 -4
  138. ansible/modules/cron.py +13 -10
  139. ansible/modules/deb822_repository.py +16 -17
  140. ansible/modules/debconf.py +25 -22
  141. ansible/modules/debug.py +1 -1
  142. ansible/modules/dnf.py +79 -164
  143. ansible/modules/dnf5.py +54 -29
  144. ansible/modules/dpkg_selections.py +2 -2
  145. ansible/modules/expect.py +2 -2
  146. ansible/modules/fetch.py +2 -2
  147. ansible/modules/file.py +5 -3
  148. ansible/modules/find.py +40 -12
  149. ansible/modules/gather_facts.py +4 -2
  150. ansible/modules/get_url.py +29 -24
  151. ansible/modules/git.py +35 -35
  152. ansible/modules/group.py +71 -1
  153. ansible/modules/hostname.py +2 -4
  154. ansible/modules/include_vars.py +5 -5
  155. ansible/modules/iptables.py +13 -16
  156. ansible/modules/known_hosts.py +16 -13
  157. ansible/modules/lineinfile.py +1 -4
  158. ansible/modules/meta.py +6 -1
  159. ansible/modules/mount_facts.py +651 -0
  160. ansible/modules/package_facts.py +63 -80
  161. ansible/modules/pause.py +4 -3
  162. ansible/modules/pip.py +14 -14
  163. ansible/modules/replace.py +1 -4
  164. ansible/modules/rpm_key.py +31 -11
  165. ansible/modules/service.py +8 -8
  166. ansible/modules/service_facts.py +20 -5
  167. ansible/modules/set_stats.py +1 -1
  168. ansible/modules/setup.py +3 -3
  169. ansible/modules/stat.py +3 -3
  170. ansible/modules/subversion.py +1 -1
  171. ansible/modules/systemd.py +16 -10
  172. ansible/modules/systemd_service.py +16 -10
  173. ansible/modules/sysvinit.py +4 -4
  174. ansible/modules/unarchive.py +35 -22
  175. ansible/modules/uri.py +24 -18
  176. ansible/modules/user.py +148 -13
  177. ansible/modules/validate_argument_spec.py +3 -3
  178. ansible/modules/wait_for_connection.py +2 -1
  179. ansible/modules/yum_repository.py +136 -179
  180. ansible/parsing/dataloader.py +2 -2
  181. ansible/parsing/mod_args.py +11 -10
  182. ansible/parsing/vault/__init__.py +8 -3
  183. ansible/parsing/yaml/constructor.py +10 -8
  184. ansible/parsing/yaml/objects.py +1 -1
  185. ansible/playbook/base.py +12 -23
  186. ansible/playbook/helpers.py +4 -0
  187. ansible/playbook/loop_control.py +8 -0
  188. ansible/playbook/play.py +4 -22
  189. ansible/playbook/play_context.py +0 -16
  190. ansible/playbook/playbook_include.py +2 -2
  191. ansible/playbook/role/__init__.py +2 -2
  192. ansible/plugins/__init__.py +2 -0
  193. ansible/plugins/action/__init__.py +7 -9
  194. ansible/plugins/action/dnf.py +7 -5
  195. ansible/plugins/action/package.py +5 -4
  196. ansible/plugins/action/reboot.py +2 -2
  197. ansible/plugins/become/__init__.py +1 -1
  198. ansible/plugins/callback/__init__.py +44 -3
  199. ansible/plugins/callback/default.py +1 -1
  200. ansible/plugins/cliconf/__init__.py +1 -1
  201. ansible/plugins/connection/paramiko_ssh.py +2 -80
  202. ansible/plugins/connection/psrp.py +33 -82
  203. ansible/plugins/connection/ssh.py +0 -8
  204. ansible/plugins/connection/winrm.py +46 -1
  205. ansible/plugins/doc_fragments/connection_pipelining.py +2 -2
  206. ansible/plugins/doc_fragments/constructed.py +10 -10
  207. ansible/plugins/doc_fragments/default_callback.py +8 -8
  208. ansible/plugins/doc_fragments/files.py +5 -5
  209. ansible/plugins/doc_fragments/inventory_cache.py +2 -2
  210. ansible/plugins/doc_fragments/result_format_callback.py +6 -6
  211. ansible/plugins/doc_fragments/return_common.py +1 -1
  212. ansible/plugins/doc_fragments/shell_common.py +2 -10
  213. ansible/plugins/doc_fragments/shell_windows.py +0 -9
  214. ansible/plugins/doc_fragments/url.py +2 -2
  215. ansible/plugins/doc_fragments/url_windows.py +4 -5
  216. ansible/plugins/doc_fragments/validate.py +1 -1
  217. ansible/plugins/filter/core.py +2 -0
  218. ansible/plugins/filter/human_to_bytes.yml +9 -0
  219. ansible/plugins/filter/password_hash.yml +1 -1
  220. ansible/plugins/filter/strftime.yml +1 -1
  221. ansible/plugins/filter/to_nice_json.yml +7 -3
  222. ansible/plugins/filter/to_uuid.yml +1 -1
  223. ansible/plugins/filter/unique.yml +28 -0
  224. ansible/plugins/inventory/script.py +1 -1
  225. ansible/plugins/list.py +1 -1
  226. ansible/plugins/loader.py +0 -11
  227. ansible/plugins/lookup/config.py +1 -1
  228. ansible/plugins/lookup/csvfile.py +21 -9
  229. ansible/plugins/lookup/env.py +8 -9
  230. ansible/plugins/lookup/ini.py +10 -1
  231. ansible/plugins/lookup/random_choice.py +2 -2
  232. ansible/plugins/lookup/url.py +7 -2
  233. ansible/plugins/shell/__init__.py +15 -20
  234. ansible/plugins/shell/powershell.py +9 -6
  235. ansible/plugins/strategy/__init__.py +18 -7
  236. ansible/plugins/strategy/linear.py +1 -13
  237. ansible/plugins/test/core.py +23 -1
  238. ansible/plugins/test/issubset.yml +1 -1
  239. ansible/plugins/test/subset.yml +1 -1
  240. ansible/plugins/test/timedout.yml +20 -0
  241. ansible/plugins/test/vault_encrypted.yml +6 -6
  242. ansible/plugins/test/vaulted_file.yml +19 -0
  243. ansible/release.py +2 -2
  244. ansible/template/__init__.py +3 -8
  245. ansible/utils/collection_loader/_collection_finder.py +23 -55
  246. ansible/utils/display.py +44 -31
  247. ansible/utils/galaxy.py +1 -1
  248. ansible/utils/jsonrpc.py +1 -1
  249. ansible/utils/listify.py +1 -5
  250. ansible/utils/path.py +3 -0
  251. ansible/utils/vars.py +18 -27
  252. ansible/vars/manager.py +7 -150
  253. ansible/vars/plugins.py +1 -1
  254. ansible_core-2.18.0rc1.dist-info/Apache-License.txt +202 -0
  255. {ansible_core-2.17.5rc1.dist-info → ansible_core-2.18.0rc1.dist-info}/METADATA +36 -23
  256. ansible_core-2.18.0rc1.dist-info/MIT-license.txt +14 -0
  257. ansible_core-2.18.0rc1.dist-info/PSF-license.txt +48 -0
  258. {ansible_core-2.17.5rc1.dist-info → ansible_core-2.18.0rc1.dist-info}/RECORD +321 -316
  259. {ansible_core-2.17.5rc1.dist-info → ansible_core-2.18.0rc1.dist-info}/entry_points.txt +1 -1
  260. ansible_core-2.18.0rc1.dist-info/simplified_bsd.txt +8 -0
  261. ansible_test/_data/completion/docker.txt +7 -7
  262. ansible_test/_data/completion/remote.txt +5 -4
  263. ansible_test/_data/completion/windows.txt +4 -4
  264. ansible_test/_data/requirements/ansible-test.txt +1 -2
  265. ansible_test/_data/requirements/constraints.txt +1 -2
  266. ansible_test/_data/requirements/sanity.ansible-doc.txt +3 -3
  267. ansible_test/_data/requirements/sanity.changelog.in +1 -1
  268. ansible_test/_data/requirements/sanity.changelog.txt +4 -4
  269. ansible_test/_data/requirements/sanity.import.plugin.txt +2 -2
  270. ansible_test/_data/requirements/sanity.import.txt +1 -1
  271. ansible_test/_data/requirements/sanity.integration-aliases.txt +1 -1
  272. ansible_test/_data/requirements/sanity.pep8.txt +1 -1
  273. ansible_test/_data/requirements/sanity.pylint.txt +6 -8
  274. ansible_test/_data/requirements/sanity.runtime-metadata.txt +2 -2
  275. ansible_test/_data/requirements/sanity.validate-modules.txt +3 -3
  276. ansible_test/_data/requirements/sanity.yamllint.in +1 -0
  277. ansible_test/_data/requirements/sanity.yamllint.txt +1 -1
  278. ansible_test/_internal/ansible_util.py +8 -35
  279. ansible_test/_internal/ci/azp.py +1 -1
  280. ansible_test/_internal/classification/__init__.py +0 -2
  281. ansible_test/_internal/cli/parsers/key_value_parsers.py +3 -0
  282. ansible_test/_internal/commands/integration/cloud/hcloud.py +1 -1
  283. ansible_test/_internal/commands/integration/cloud/httptester.py +1 -1
  284. ansible_test/_internal/commands/integration/cloud/nios.py +1 -1
  285. ansible_test/_internal/commands/sanity/__init__.py +96 -19
  286. ansible_test/_internal/commands/sanity/pylint.py +20 -24
  287. ansible_test/_internal/completion.py +2 -0
  288. ansible_test/_internal/constants.py +0 -1
  289. ansible_test/_internal/coverage_util.py +1 -2
  290. ansible_test/_internal/docker_util.py +10 -2
  291. ansible_test/_internal/encoding.py +4 -4
  292. ansible_test/_internal/host_configs.py +10 -0
  293. ansible_test/_internal/host_profiles.py +9 -13
  294. ansible_test/_internal/pypi_proxy.py +1 -1
  295. ansible_test/_internal/python_requirements.py +5 -14
  296. ansible_test/_internal/timeout.py +1 -1
  297. ansible_test/_internal/util.py +56 -8
  298. ansible_test/_internal/util_common.py +5 -1
  299. ansible_test/_util/controller/sanity/code-smell/action-plugin-docs.json +3 -1
  300. ansible_test/_util/controller/sanity/code-smell/action-plugin-docs.py +6 -3
  301. ansible_test/_util/controller/sanity/code-smell/empty-init.json +0 -2
  302. ansible_test/_util/controller/sanity/pylint/config/ansible-test-target.cfg +5 -0
  303. ansible_test/_util/controller/sanity/pylint/config/ansible-test.cfg +5 -0
  304. ansible_test/_util/controller/sanity/pylint/config/code-smell.cfg +5 -0
  305. ansible_test/_util/controller/sanity/pylint/config/collection.cfg +6 -0
  306. ansible_test/_util/controller/sanity/pylint/config/default.cfg +6 -0
  307. ansible_test/_util/controller/sanity/pylint/plugins/deprecated.py +1 -19
  308. ansible_test/_util/controller/sanity/pylint/plugins/hide_unraisable.py +3 -4
  309. ansible_test/_util/controller/sanity/shellcheck/exclude.txt +1 -0
  310. ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py +67 -2
  311. ansible_test/_util/controller/sanity/validate-modules/validate_modules/schema.py +27 -5
  312. ansible_test/_util/target/cli/ansible_test_cli_stub.py +0 -0
  313. ansible_test/_util/target/common/constants.py +2 -2
  314. ansible_test/_util/target/injector/python.py +5 -0
  315. ansible_test/_util/target/pytest/plugins/ansible_pytest_coverage.py +6 -0
  316. ansible_test/_util/target/sanity/import/importer.py +1 -1
  317. ansible_test/_util/target/setup/bootstrap.sh +6 -17
  318. ansible_test/_util/target/setup/requirements.py +18 -24
  319. ansible_test/config/config.yml +1 -1
  320. ansible_core-2.17.5rc1.data/scripts/ansible-test +0 -44
  321. ansible_test/_data/requirements/sanity.mypy.in +0 -10
  322. ansible_test/_data/requirements/sanity.mypy.txt +0 -18
  323. ansible_test/_internal/commands/sanity/mypy.py +0 -274
  324. ansible_test/_util/controller/sanity/mypy/ansible-core.ini +0 -116
  325. ansible_test/_util/controller/sanity/mypy/ansible-test.ini +0 -27
  326. ansible_test/_util/controller/sanity/mypy/modules.ini +0 -92
  327. ansible_test/_util/controller/sanity/mypy/packaging.ini +0 -20
  328. {ansible_core-2.17.5rc1.dist-info → ansible_core-2.18.0rc1.dist-info}/COPYING +0 -0
  329. {ansible_core-2.17.5rc1.dist-info → ansible_core-2.18.0rc1.dist-info}/WHEEL +0 -0
  330. {ansible_core-2.17.5rc1.dist-info → ansible_core-2.18.0rc1.dist-info}/top_level.txt +0 -0
@@ -480,7 +480,7 @@ class JinjaPluginIntercept(MutableMapping):
480
480
  if self._pluginloader.type == 'filter':
481
481
  # filter need wrapping
482
482
  if key in C.STRING_TYPE_FILTERS:
483
- # avoid litera_eval when you WANT strings
483
+ # avoid literal_eval when you WANT strings
484
484
  func = _wrap_native_text(func)
485
485
  else:
486
486
  # conditionally unroll iterators/generators to avoid having to use `|list` after every filter
@@ -706,7 +706,7 @@ class Templar:
706
706
  setattr(obj, key, original[key])
707
707
 
708
708
  def template(self, variable, convert_bare=False, preserve_trailing_newlines=True, escape_backslashes=True, fail_on_undefined=None, overrides=None,
709
- convert_data=True, static_vars=None, cache=None, disable_lookups=False):
709
+ convert_data=True, static_vars=None, disable_lookups=False):
710
710
  '''
711
711
  Templates (possibly recursively) any given data as input. If convert_bare is
712
712
  set to True, the given data will be wrapped as a jinja2 variable ('{{foo}}')
@@ -714,9 +714,6 @@ class Templar:
714
714
  '''
715
715
  static_vars = [] if static_vars is None else static_vars
716
716
 
717
- if cache is not None:
718
- display.deprecated("The `cache` option to `Templar.template` is no longer functional, and will be removed in a future release.", version='2.18')
719
-
720
717
  # Don't template unsafe variables, just return them.
721
718
  if hasattr(variable, '__UNSAFE__'):
722
719
  return variable
@@ -883,11 +880,9 @@ class Templar:
883
880
  return [] if wantlist else None
884
881
 
885
882
  if not is_sequence(ran):
886
- display.deprecated(
883
+ raise AnsibleLookupError(
887
884
  f'The lookup plugin \'{name}\' was expected to return a list, got \'{type(ran)}\' instead. '
888
885
  f'The lookup plugin \'{name}\' needs to be changed to return a list. '
889
- 'This will be an error in Ansible 2.18',
890
- version='2.18'
891
886
  )
892
887
 
893
888
  if ran and allow_unsafe is False:
@@ -9,17 +9,14 @@ from __future__ import annotations
9
9
  import itertools
10
10
  import os
11
11
  import os.path
12
- import pkgutil
13
12
  import re
14
13
  import sys
15
14
  from keyword import iskeyword
16
- from tokenize import Name as _VALID_IDENTIFIER_REGEX
17
15
 
18
16
 
19
17
  # DO NOT add new non-stdlib import deps here, this loader is used by external tools (eg ansible-test import sanity)
20
18
  # that only allow stdlib and module_utils
21
19
  from ansible.module_utils.common.text.converters import to_native, to_text, to_bytes
22
- from ansible.module_utils.six import string_types, PY3
23
20
  from ._collection_config import AnsibleCollectionConfig
24
21
 
25
22
  from contextlib import contextmanager
@@ -32,11 +29,7 @@ except ImportError:
32
29
  __import__(name)
33
30
  return sys.modules[name]
34
31
 
35
- try:
36
- from importlib import reload as reload_module
37
- except ImportError:
38
- # 2.7 has a global reload function instead...
39
- reload_module = reload # type: ignore[name-defined] # pylint:disable=undefined-variable
32
+ from importlib import reload as reload_module
40
33
 
41
34
  try:
42
35
  try:
@@ -77,26 +70,7 @@ try:
77
70
  except ImportError:
78
71
  _meta_yml_to_dict = None
79
72
 
80
-
81
- if not hasattr(__builtins__, 'ModuleNotFoundError'):
82
- # this was introduced in Python 3.6
83
- ModuleNotFoundError = ImportError
84
-
85
-
86
- _VALID_IDENTIFIER_STRING_REGEX = re.compile(
87
- ''.join((_VALID_IDENTIFIER_REGEX, r'\Z')),
88
- )
89
-
90
-
91
- try: # NOTE: py3/py2 compat
92
- # py2 mypy can't deal with try/excepts
93
- is_python_identifier = str.isidentifier # type: ignore[attr-defined]
94
- except AttributeError: # Python 2
95
- def is_python_identifier(self): # type: (str) -> bool
96
- """Determine whether the given string is a Python identifier."""
97
- # Ref: https://stackoverflow.com/a/55802320/595220
98
- return bool(re.match(_VALID_IDENTIFIER_STRING_REGEX, self))
99
-
73
+ is_python_identifier = str.isidentifier # type: ignore[attr-defined]
100
74
 
101
75
  PB_EXTENSIONS = ('.yml', '.yaml')
102
76
  SYNTHETIC_PACKAGE_NAME = '<ansible_synthetic_collection_package>'
@@ -219,7 +193,7 @@ class _AnsibleTraversableResources(TraversableResources):
219
193
  parts = package.split('.')
220
194
  is_ns = parts[0] == 'ansible_collections' and len(parts) < 3
221
195
 
222
- if isinstance(package, string_types):
196
+ if isinstance(package, str):
223
197
  if is_ns:
224
198
  # Don't use ``spec_from_loader`` here, because that will point
225
199
  # to exactly 1 location for a namespace. Use ``find_spec``
@@ -241,7 +215,7 @@ class _AnsibleCollectionFinder:
241
215
  # TODO: accept metadata loader override
242
216
  self._ansible_pkg_path = to_native(os.path.dirname(to_bytes(sys.modules['ansible'].__file__)))
243
217
 
244
- if isinstance(paths, string_types):
218
+ if isinstance(paths, str):
245
219
  paths = [paths]
246
220
  elif paths is None:
247
221
  paths = []
@@ -326,7 +300,7 @@ class _AnsibleCollectionFinder:
326
300
  return paths
327
301
 
328
302
  def set_playbook_paths(self, playbook_paths):
329
- if isinstance(playbook_paths, string_types):
303
+ if isinstance(playbook_paths, str):
330
304
  playbook_paths = [playbook_paths]
331
305
 
332
306
  # track visited paths; we have to preserve the dir order as-passed in case there are duplicate collections (first one wins)
@@ -412,19 +386,17 @@ class _AnsiblePathHookFinder:
412
386
  # when called from a path_hook, find_module doesn't usually get the path arg, so this provides our context
413
387
  self._pathctx = to_native(pathctx)
414
388
  self._collection_finder = collection_finder
415
- if PY3:
416
- # cache the native FileFinder (take advantage of its filesystem cache for future find/load requests)
417
- self._file_finder = None
389
+ # cache the native FileFinder (take advantage of its filesystem cache for future find/load requests)
390
+ self._file_finder = None
418
391
 
419
392
  # class init is fun- this method has a self arg that won't get used
420
393
  def _get_filefinder_path_hook(self=None):
421
394
  _file_finder_hook = None
422
- if PY3:
423
- # try to find the FileFinder hook to call for fallback path-based imports in Py3
424
- _file_finder_hook = [ph for ph in sys.path_hooks if 'FileFinder' in repr(ph)]
425
- if len(_file_finder_hook) != 1:
426
- raise Exception('need exactly one FileFinder import hook (found {0})'.format(len(_file_finder_hook)))
427
- _file_finder_hook = _file_finder_hook[0]
395
+ # try to find the FileFinder hook to call for fallback path-based imports in Py3
396
+ _file_finder_hook = [ph for ph in sys.path_hooks if 'FileFinder' in repr(ph)]
397
+ if len(_file_finder_hook) != 1:
398
+ raise Exception('need exactly one FileFinder import hook (found {0})'.format(len(_file_finder_hook)))
399
+ _file_finder_hook = _file_finder_hook[0]
428
400
 
429
401
  return _file_finder_hook
430
402
 
@@ -445,20 +417,16 @@ class _AnsiblePathHookFinder:
445
417
  # out what we *shouldn't* be loading with the limited info it has. So we'll just delegate to the
446
418
  # normal path-based loader as best we can to service it. This also allows us to take advantage of Python's
447
419
  # built-in FS caching and byte-compilation for most things.
448
- if PY3:
449
- # create or consult our cached file finder for this path
450
- if not self._file_finder:
451
- try:
452
- self._file_finder = _AnsiblePathHookFinder._filefinder_path_hook(self._pathctx)
453
- except ImportError:
454
- # FUTURE: log at a high logging level? This is normal for things like python36.zip on the path, but
455
- # might not be in some other situation...
456
- return None
457
-
458
- return self._file_finder
420
+ # create or consult our cached file finder for this path
421
+ if not self._file_finder:
422
+ try:
423
+ self._file_finder = _AnsiblePathHookFinder._filefinder_path_hook(self._pathctx)
424
+ except ImportError:
425
+ # FUTURE: log at a high logging level? This is normal for things like python36.zip on the path, but
426
+ # might not be in some other situation...
427
+ return None
459
428
 
460
- # call py2's internal loader
461
- return pkgutil.ImpImporter(self._pathctx)
429
+ return self._file_finder
462
430
 
463
431
  def find_module(self, fullname, path=None):
464
432
  # we ignore the passed in path here- use what we got from the path hook init
@@ -1124,7 +1092,7 @@ class AnsibleCollectionRef:
1124
1092
 
1125
1093
  def _get_collection_path(collection_name):
1126
1094
  collection_name = to_native(collection_name)
1127
- if not collection_name or not isinstance(collection_name, string_types) or len(collection_name.split('.')) != 2:
1095
+ if not collection_name or not isinstance(collection_name, str) or len(collection_name.split('.')) != 2:
1128
1096
  raise ValueError('collection_name must be a non-empty string of the form namespace.collection')
1129
1097
  try:
1130
1098
  collection_pkg = import_module('ansible_collections.' + collection_name)
@@ -1307,7 +1275,7 @@ def _iter_modules_impl(paths, prefix=''):
1307
1275
 
1308
1276
  def _get_collection_metadata(collection_name):
1309
1277
  collection_name = to_native(collection_name)
1310
- if not collection_name or not isinstance(collection_name, string_types) or len(collection_name.split('.')) != 2:
1278
+ if not collection_name or not isinstance(collection_name, str) or len(collection_name.split('.')) != 2:
1311
1279
  raise ValueError('collection_name must be a non-empty string of the form namespace.collection')
1312
1280
 
1313
1281
  try:
ansible/utils/display.py CHANGED
@@ -33,7 +33,7 @@ import getpass
33
33
  import io
34
34
  import logging
35
35
  import os
36
- import random
36
+ import secrets
37
37
  import subprocess
38
38
  import sys
39
39
  import termios
@@ -154,27 +154,31 @@ logger = None
154
154
  if getattr(C, 'DEFAULT_LOG_PATH'):
155
155
  path = C.DEFAULT_LOG_PATH
156
156
  if path and (os.path.exists(path) and os.access(path, os.W_OK)) or os.access(os.path.dirname(path), os.W_OK):
157
- # NOTE: level is kept at INFO to avoid security disclosures caused by certain libraries when using DEBUG
158
- logging.basicConfig(filename=path, level=logging.INFO, # DO NOT set to logging.DEBUG
159
- format='%(asctime)s p=%(process)d u=%(user)s n=%(name)s | %(message)s')
160
-
161
- logger = logging.getLogger('ansible')
162
- for handler in logging.root.handlers:
163
- handler.addFilter(FilterBlackList(getattr(C, 'DEFAULT_LOG_FILTER', [])))
164
- handler.addFilter(FilterUserInjector())
157
+ if not os.path.isdir(path):
158
+ # NOTE: level is kept at INFO to avoid security disclosures caused by certain libraries when using DEBUG
159
+ logging.basicConfig(filename=path, level=logging.INFO, # DO NOT set to logging.DEBUG
160
+ format='%(asctime)s p=%(process)d u=%(user)s n=%(name)s %(levelname)s| %(message)s')
161
+
162
+ logger = logging.getLogger('ansible')
163
+ for handler in logging.root.handlers:
164
+ handler.addFilter(FilterBlackList(getattr(C, 'DEFAULT_LOG_FILTER', [])))
165
+ handler.addFilter(FilterUserInjector())
166
+ else:
167
+ print(f"[WARNING]: DEFAULT_LOG_PATH can not be a directory '{path}', aborting", file=sys.stderr)
165
168
  else:
166
- print("[WARNING]: log file at %s is not writeable and we cannot create it, aborting\n" % path, file=sys.stderr)
169
+ print(f"[WARNING]: log file at '{path}' is not writeable and we cannot create it, aborting\n", file=sys.stderr)
167
170
 
168
- # map color to log levels
169
- color_to_log_level = {C.COLOR_ERROR: logging.ERROR,
170
- C.COLOR_WARN: logging.WARNING,
171
+ # map color to log levels, in order of priority (low to high)
172
+ color_to_log_level = {C.COLOR_DEBUG: logging.DEBUG,
173
+ C.COLOR_VERBOSE: logging.INFO,
171
174
  C.COLOR_OK: logging.INFO,
172
- C.COLOR_SKIP: logging.WARNING,
173
- C.COLOR_UNREACHABLE: logging.ERROR,
174
- C.COLOR_DEBUG: logging.DEBUG,
175
+ C.COLOR_INCLUDED: logging.INFO,
175
176
  C.COLOR_CHANGED: logging.INFO,
177
+ C.COLOR_SKIP: logging.WARNING,
176
178
  C.COLOR_DEPRECATE: logging.WARNING,
177
- C.COLOR_VERBOSE: logging.INFO}
179
+ C.COLOR_WARN: logging.WARNING,
180
+ C.COLOR_UNREACHABLE: logging.ERROR,
181
+ C.COLOR_ERROR: logging.ERROR}
178
182
 
179
183
  b_COW_PATHS = (
180
184
  b"/usr/bin/cowsay",
@@ -310,8 +314,8 @@ class Display(metaclass=Singleton):
310
314
 
311
315
  codecs.register_error('_replacing_warning_handler', self._replacing_warning_handler)
312
316
  try:
313
- sys.stdout.reconfigure(errors='_replacing_warning_handler')
314
- sys.stderr.reconfigure(errors='_replacing_warning_handler')
317
+ sys.stdout.reconfigure(errors='_replacing_warning_handler') # type: ignore[union-attr]
318
+ sys.stderr.reconfigure(errors='_replacing_warning_handler') # type: ignore[union-attr]
315
319
  except Exception as ex:
316
320
  self.warning(f"failed to reconfigure stdout/stderr with custom encoding error handler: {ex}")
317
321
 
@@ -398,6 +402,7 @@ class Display(metaclass=Singleton):
398
402
  screen_only: bool = False,
399
403
  log_only: bool = False,
400
404
  newline: bool = True,
405
+ caplevel: int | None = None,
401
406
  ) -> None:
402
407
  """ Display a message to the user
403
408
 
@@ -424,7 +429,7 @@ class Display(metaclass=Singleton):
424
429
  msg2 = msg2 + u'\n'
425
430
 
426
431
  # Note: After Display() class is refactored need to update the log capture
427
- # code in 'bin/ansible-connection' (and other relevant places).
432
+ # code in 'cli/scripts/ansible_connection_cli_stub.py' (and other relevant places).
428
433
  if not stderr:
429
434
  fileobj = sys.stdout
430
435
  else:
@@ -447,20 +452,28 @@ class Display(metaclass=Singleton):
447
452
  # raise
448
453
 
449
454
  if logger and not screen_only:
450
- self._log(nocolor, color)
455
+ self._log(nocolor, color, caplevel)
451
456
 
452
457
  def _log(self, msg: str, color: str | None = None, caplevel: int | None = None):
453
458
 
454
459
  if logger and (caplevel is None or self.log_verbosity > caplevel):
455
460
  msg2 = msg.lstrip('\n')
456
461
 
457
- lvl = logging.INFO
458
- if color:
462
+ if caplevel is None or caplevel > 0:
463
+ lvl = logging.INFO
464
+ elif caplevel == -1:
465
+ lvl = logging.ERROR
466
+ elif caplevel == -2:
467
+ lvl = logging.WARNING
468
+ elif caplevel == -3:
469
+ lvl = logging.DEBUG
470
+ elif color:
459
471
  # set logger level based on color (not great)
472
+ # but last resort and backwards compatible
460
473
  try:
461
474
  lvl = color_to_log_level[color]
462
475
  except KeyError:
463
- # this should not happen, but JIC
476
+ # this should not happen if mapping is updated with new color configs, but JIC
464
477
  raise AnsibleAssertionError('Invalid color supplied to display: %s' % color)
465
478
 
466
479
  # actually log
@@ -509,10 +522,10 @@ class Display(metaclass=Singleton):
509
522
  @_meets_debug
510
523
  @_proxy
511
524
  def debug(self, msg: str, host: str | None = None) -> None:
512
- if host is None:
513
- self.display("%6d %0.5f: %s" % (os.getpid(), time.time(), msg), color=C.COLOR_DEBUG)
514
- else:
515
- self.display("%6d %0.5f [%s]: %s" % (os.getpid(), time.time(), host, msg), color=C.COLOR_DEBUG)
525
+ prefix = "%6d %0.5f" % (os.getpid(), time.time())
526
+ if host is not None:
527
+ prefix += f" [{host}]"
528
+ self.display(f"{prefix}: {msg}", color=C.COLOR_DEBUG, caplevel=-3)
516
529
 
517
530
  def get_deprecation_message(
518
531
  self,
@@ -591,7 +604,7 @@ class Display(metaclass=Singleton):
591
604
  new_msg = "\n[WARNING]: \n%s" % msg
592
605
 
593
606
  if new_msg not in self._warns:
594
- self.display(new_msg, color=C.COLOR_WARN, stderr=True)
607
+ self.display(new_msg, color=C.COLOR_WARN, stderr=True, caplevel=-2)
595
608
  self._warns[new_msg] = 1
596
609
 
597
610
  @_proxy
@@ -633,7 +646,7 @@ class Display(metaclass=Singleton):
633
646
  if self.noncow:
634
647
  thecow = self.noncow
635
648
  if thecow == 'random':
636
- thecow = random.choice(list(self.cows_available))
649
+ thecow = secrets.choice(list(self.cows_available))
637
650
  runcmd.append(b'-f')
638
651
  runcmd.append(to_bytes(thecow))
639
652
  runcmd.append(to_bytes(msg))
@@ -650,7 +663,7 @@ class Display(metaclass=Singleton):
650
663
  else:
651
664
  new_msg = u"ERROR! %s" % msg
652
665
  if new_msg not in self._errors:
653
- self.display(new_msg, color=C.COLOR_ERROR, stderr=True)
666
+ self.display(new_msg, color=C.COLOR_ERROR, stderr=True, caplevel=-1)
654
667
  self._errors[new_msg] = 1
655
668
 
656
669
  @staticmethod
ansible/utils/galaxy.py CHANGED
@@ -64,7 +64,7 @@ def scm_archive_resource(src, scm='git', name=None, version='HEAD', keep_scm_met
64
64
  clone_cmd = [scm_path, 'clone']
65
65
 
66
66
  # Add specific options for ignoring certificates if requested
67
- ignore_certs = context.CLIARGS['ignore_certs']
67
+ ignore_certs = context.CLIARGS['ignore_certs'] or C.GALAXY_IGNORE_CERTS
68
68
 
69
69
  if ignore_certs:
70
70
  if scm == 'git':
ansible/utils/jsonrpc.py CHANGED
@@ -83,7 +83,7 @@ class JsonRpcServer(object):
83
83
  result = to_text(result)
84
84
  if not isinstance(result, text_type):
85
85
  response["result_type"] = "pickle"
86
- result = to_text(pickle.dumps(result, protocol=0))
86
+ result = to_text(pickle.dumps(result), errors='surrogateescape')
87
87
  response['result'] = result
88
88
  return response
89
89
 
ansible/utils/listify.py CHANGED
@@ -27,11 +27,7 @@ display = Display()
27
27
  __all__ = ['listify_lookup_plugin_terms']
28
28
 
29
29
 
30
- def listify_lookup_plugin_terms(terms, templar, loader=None, fail_on_undefined=True, convert_bare=False):
31
-
32
- if loader is not None:
33
- display.deprecated('"listify_lookup_plugin_terms" does not use "dataloader" anymore, the ability to pass it in will be removed in future versions.',
34
- version='2.18')
30
+ def listify_lookup_plugin_terms(terms, templar, fail_on_undefined=True, convert_bare=False):
35
31
 
36
32
  if isinstance(terms, string_types):
37
33
  terms = templar.template(terms.strip(), convert_bare=convert_bare, fail_on_undefined=fail_on_undefined)
ansible/utils/path.py CHANGED
@@ -33,6 +33,9 @@ def unfrackpath(path, follow=True, basedir=None):
33
33
 
34
34
  :arg path: A byte or text string representing a path to be canonicalized
35
35
  :arg follow: A boolean to indicate of symlinks should be resolved or not
36
+ :arg basedir: A byte string, text string, PathLike object, or `None`
37
+ representing where a relative path should be resolved from.
38
+ `None` will be substituted for the current working directory.
36
39
  :raises UnicodeDecodeError: If the canonicalized version of the path
37
40
  contains non-utf8 byte sequences.
38
41
  :rtype: A text string (unicode on pyyhon2, str on python3).
ansible/utils/vars.py CHANGED
@@ -18,7 +18,7 @@
18
18
  from __future__ import annotations
19
19
 
20
20
  import keyword
21
- import random
21
+ import secrets
22
22
  import uuid
23
23
 
24
24
  from collections.abc import MutableMapping, MutableSequence
@@ -32,12 +32,10 @@ from ansible.module_utils.common.text.converters import to_native, to_text
32
32
  from ansible.parsing.splitter import parse_kv
33
33
 
34
34
 
35
- ADDITIONAL_PY2_KEYWORDS = frozenset(("True", "False", "None"))
36
-
37
35
  _MAXSIZE = 2 ** 32
38
36
  cur_id = 0
39
37
  node_mac = ("%012x" % uuid.getnode())[:12]
40
- random_int = ("%08x" % random.randint(0, _MAXSIZE))[:8]
38
+ random_int = ("%08x" % secrets.randbelow(_MAXSIZE))[:8]
41
39
 
42
40
 
43
41
  def get_unique_id():
@@ -237,7 +235,22 @@ def load_options_vars(version):
237
235
  return load_options_vars.options_vars
238
236
 
239
237
 
240
- def _isidentifier_PY3(ident):
238
+ def isidentifier(ident):
239
+ """Determine if string is valid identifier.
240
+
241
+ The purpose of this function is to be used to validate any variables created in
242
+ a play to be valid Python identifiers and to not conflict with Python keywords
243
+ to prevent unexpected behavior. Since Python 2 and Python 3 differ in what
244
+ a valid identifier is, this function unifies the validation so playbooks are
245
+ portable between the two. The following changes were made:
246
+
247
+ * disallow non-ascii characters (Python 3 allows for them as opposed to Python 2)
248
+
249
+ :arg ident: A text string of identifier to check. Note: It is callers
250
+ responsibility to convert ident to text if it is not already.
251
+
252
+ Originally posted at https://stackoverflow.com/a/29586366
253
+ """
241
254
  if not isinstance(ident, string_types):
242
255
  return False
243
256
 
@@ -251,25 +264,3 @@ def _isidentifier_PY3(ident):
251
264
  return False
252
265
 
253
266
  return True
254
-
255
-
256
- isidentifier = _isidentifier_PY3
257
-
258
-
259
- isidentifier.__doc__ = """Determine if string is valid identifier.
260
-
261
- The purpose of this function is to be used to validate any variables created in
262
- a play to be valid Python identifiers and to not conflict with Python keywords
263
- to prevent unexpected behavior. Since Python 2 and Python 3 differ in what
264
- a valid identifier is, this function unifies the validation so playbooks are
265
- portable between the two. The following changes were made:
266
-
267
- * disallow non-ascii characters (Python 3 allows for them as opposed to Python 2)
268
- * True, False and None are reserved keywords (these are reserved keywords
269
- on Python 3 as opposed to Python 2)
270
-
271
- :arg ident: A text string of identifier to check. Note: It is callers
272
- responsibility to convert ident to text if it is not already.
273
-
274
- Originally posted at http://stackoverflow.com/a/29586366
275
- """