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
@@ -130,7 +130,7 @@ EXAMPLES = r'''# fmt: code
130
130
  mandatory_options = arg_parser.add_mutually_exclusive_group()
131
131
  mandatory_options.add_argument('--list', action='store', nargs="*", help="Get inventory JSON from our API")
132
132
  mandatory_options.add_argument('--host', action='store',
133
- help="Get variables for specific host, not used but kept for compatability")
133
+ help="Get variables for specific host, not used but kept for compatibility")
134
134
 
135
135
  try:
136
136
  config = load_config()
ansible/plugins/list.py CHANGED
@@ -84,7 +84,7 @@ def _list_plugins_from_paths(ptype, dirs, collection, depth=0):
84
84
  to_native(b_ext) in C.REJECT_EXTS, # general extensions to ignore
85
85
  b_ext in (b'.yml', b'.yaml', b'.json'), # ignore docs files TODO: constant!
86
86
  plugin in IGNORE.get(bkey, ()), # plugin in reject list
87
- os.path.islink(full_path), # skip aliases, author should document in 'aliaes' field
87
+ os.path.islink(full_path), # skip aliases, author should document in 'aliases' field
88
88
  ]):
89
89
  continue
90
90
 
ansible/plugins/loader.py CHANGED
@@ -1110,10 +1110,6 @@ class PluginLoader:
1110
1110
  needs_enabled = False
1111
1111
  if hasattr(obj, 'REQUIRES_ENABLED'):
1112
1112
  needs_enabled = obj.REQUIRES_ENABLED
1113
- elif hasattr(obj, 'REQUIRES_WHITELIST'):
1114
- needs_enabled = obj.REQUIRES_WHITELIST
1115
- display.deprecated("The VarsModule class variable 'REQUIRES_WHITELIST' is deprecated. "
1116
- "Use 'REQUIRES_ENABLED' instead.", version=2.18)
1117
1113
  if not needs_enabled:
1118
1114
  # Use get_with_context to cache the plugin the first time we see it.
1119
1115
  self.get_with_context(fqcn)[0]
@@ -1424,13 +1420,6 @@ def _load_plugin_filter():
1424
1420
  # Modules and action plugins share the same reject list since the difference between the
1425
1421
  # two isn't visible to the users
1426
1422
  if version == u'1.0':
1427
-
1428
- if 'module_blacklist' in filter_data:
1429
- display.deprecated("'module_blacklist' is being removed in favor of 'module_rejectlist'", version='2.18')
1430
- if 'module_rejectlist' not in filter_data:
1431
- filter_data['module_rejectlist'] = filter_data['module_blacklist']
1432
- del filter_data['module_blacklist']
1433
-
1434
1423
  try:
1435
1424
  filters['ansible.modules'] = frozenset(filter_data['module_rejectlist'])
1436
1425
  except TypeError:
@@ -8,7 +8,7 @@ DOCUMENTATION = """
8
8
  version_added: "2.5"
9
9
  short_description: Display the 'resolved' Ansible option values.
10
10
  description:
11
- - Retrieves the value of an Ansible configuration setting, resolving all sources, from defaults, ansible.cfg, envirionmnet,
11
+ - Retrieves the value of an Ansible configuration setting, resolving all sources, from defaults, ansible.cfg, environment,
12
12
  CLI, and variables, but not keywords.
13
13
  - The values returned assume the context of the current host or C(inventory_hostname).
14
14
  - You can use C(ansible-config list) to see the global available settings, add C(-t all) to also show plugin options.
@@ -52,18 +52,30 @@ EXAMPLES = """
52
52
  - name: msg="Match 'Li' on the first column, but return the 3rd column (columns start counting after the match)"
53
53
  ansible.builtin.debug: msg="The atomic mass of Lithium is {{ lookup('ansible.builtin.csvfile', 'Li file=elements.csv delimiter=, col=2') }}"
54
54
 
55
- - name: Define Values From CSV File, this reads file in one go, but you could also use col= to read each in it's own lookup.
55
+ # Contents of bgp_neighbors.csv
56
+ # 127.0.0.1,10.0.0.1,24,nones,lola,pepe,127.0.0.2
57
+ # 128.0.0.1,10.1.0.1,20,notes,lolita,pepito,128.0.0.2
58
+ # 129.0.0.1,10.2.0.1,23,nines,aayush,pepete,129.0.0.2
59
+
60
+ - name: Define values from CSV file, this reads file in one go, but you could also use col= to read each in it's own lookup.
56
61
  ansible.builtin.set_fact:
57
- loop_ip: "{{ csvline[0] }}"
58
- int_ip: "{{ csvline[1] }}"
59
- int_mask: "{{ csvline[2] }}"
60
- int_name: "{{ csvline[3] }}"
61
- local_as: "{{ csvline[4] }}"
62
- neighbor_as: "{{ csvline[5] }}"
63
- neigh_int_ip: "{{ csvline[6] }}"
62
+ '{{ columns[item|int] }}': "{{ csvline }}"
64
63
  vars:
65
- csvline: "{{ lookup('ansible.builtin.csvfile', bgp_neighbor_ip, file='bgp_neighbors.csv', delimiter=',') }}"
64
+ csvline: "{{ lookup('csvfile', bgp_neighbor_ip, file='bgp_neighbors.csv', delimiter=',', col=item) }}"
65
+ columns: ['loop_ip', 'int_ip', 'int_mask', 'int_name', 'local_as', 'neighbour_as', 'neight_int_ip']
66
+ bgp_neighbor_ip: '127.0.0.1'
67
+ loop: '{{ range(columns|length|int) }}'
66
68
  delegate_to: localhost
69
+ delegate_facts: true
70
+
71
+ # Contents of people.csv
72
+ # # Last,First,Email,Extension
73
+ # Smith,Jane,jsmith@example.com,1234
74
+
75
+ - name: Specify the column (by keycol) in which the string should be searched
76
+ assert:
77
+ that:
78
+ - lookup('ansible.builtin.csvfile', 'Jane', file='people.csv', delimiter=',', col=0, keycol=1) == "Smith"
67
79
 
68
80
  # Contents of debug.csv
69
81
  # test1 ret1.1 ret2.1
@@ -30,22 +30,21 @@ EXAMPLES = """
30
30
  ansible.builtin.debug:
31
31
  msg: "'{{ lookup('ansible.builtin.env', 'HOME') }}' is the HOME environment variable."
32
32
 
33
- - name: Before 2.13, how to set default value if the variable is not defined.
34
- This cannot distinguish between USR undefined and USR=''.
33
+ - name: Before 2.13, how to set default value if the variable is not defined
35
34
  ansible.builtin.debug:
36
- msg: "{{ lookup('ansible.builtin.env', 'USR')|default('nobody', True) }} is the user."
35
+ msg: "Hello {{ lookup('ansible.builtin.env', 'UNDEFINED_VARIABLE') | default('World', True) }}"
37
36
 
38
- - name: Example how to set default value if the variable is not defined, ignores USR=''
37
+ - name: Example how to set default value if the variable is not defined
39
38
  ansible.builtin.debug:
40
- msg: "{{ lookup('ansible.builtin.env', 'USR', default='nobody') }} is the user."
39
+ msg: "Hello {{ lookup('ansible.builtin.env', 'UNDEFINED_VARIABLE', default='World') }}"
41
40
 
42
- - name: Set default value to Undefined, if the variable is not defined
41
+ - name: Fail if the variable is not defined by setting default value to 'Undefined'
43
42
  ansible.builtin.debug:
44
- msg: "{{ lookup('ansible.builtin.env', 'USR', default=Undefined) }} is the user."
43
+ msg: "Hello {{ lookup('ansible.builtin.env', 'UNDEFINED_VARIABLE', default=Undefined) }}"
45
44
 
46
- - name: Set default value to undef(), if the variable is not defined
45
+ - name: Fail if the variable is not defined by setting default value to 'undef()'
47
46
  ansible.builtin.debug:
48
- msg: "{{ lookup('ansible.builtin.env', 'USR', default=undef()) }} is the user."
47
+ msg: "Hello {{ lookup('ansible.builtin.env', 'UNDEFINED_VARIABLE', default=undef()) }}"
49
48
  """
50
49
 
51
50
  RETURN = """
@@ -49,6 +49,12 @@ DOCUMENTATION = """
49
49
  default: False
50
50
  aliases: ['allow_none']
51
51
  version_added: '2.12'
52
+ interpolation:
53
+ description:
54
+ Allows for interpolation of values, see https://docs.python.org/3/library/configparser.html#configparser.BasicInterpolation
55
+ type: bool
56
+ default: True
57
+ version_added: '2.18'
52
58
  seealso:
53
59
  - ref: playbook_task_paths
54
60
  description: Search paths used for relative files.
@@ -140,7 +146,10 @@ class LookupModule(LookupBase):
140
146
  self.set_options(var_options=variables, direct=kwargs)
141
147
  paramvals = self.get_options()
142
148
 
143
- self.cp = configparser.ConfigParser(allow_no_value=paramvals.get('allow_no_value', paramvals.get('allow_none')))
149
+ self.cp = configparser.ConfigParser(
150
+ allow_no_value=paramvals.get('allow_no_value', paramvals.get('allow_none')),
151
+ interpolation=configparser.BasicInterpolation() if paramvals.get('interpolation') else None,
152
+ )
144
153
  if paramvals['case_sensitive']:
145
154
  self.cp.optionxform = to_native
146
155
 
@@ -31,7 +31,7 @@ RETURN = """
31
31
  - random item
32
32
  type: raw
33
33
  """
34
- import random
34
+ import secrets
35
35
 
36
36
  from ansible.errors import AnsibleError
37
37
  from ansible.module_utils.common.text.converters import to_native
@@ -45,7 +45,7 @@ class LookupModule(LookupBase):
45
45
  ret = terms
46
46
  if terms:
47
47
  try:
48
- ret = [random.choice(terms)]
48
+ ret = [secrets.choice(terms)]
49
49
  except Exception as e:
50
50
  raise AnsibleError("Unable to choose random term: %s" % to_native(e))
51
51
 
@@ -103,8 +103,8 @@ options:
103
103
  none: Will not follow any redirects.
104
104
  safe: Only redirects doing GET or HEAD requests will be followed.
105
105
  urllib2: Defer to urllib2 behavior (As of writing this follows HTTP redirects).
106
- 'no': (DEPRECATED, will be removed in the future version) alias of V(none).
107
- 'yes': (DEPRECATED, will be removed in the future version) alias of V(all).
106
+ 'no': (DEPRECATED, removed in 2.22) alias of V(none).
107
+ 'yes': (DEPRECATED, removed in 2.22) alias of V(all).
108
108
  use_gssapi:
109
109
  description:
110
110
  - Use GSSAPI handler of requests
@@ -234,6 +234,11 @@ class LookupModule(LookupBase):
234
234
  ret = []
235
235
  for term in terms:
236
236
  display.vvvv("url lookup connecting to %s" % term)
237
+ if self.get_option('follow_redirects') in ('yes', 'no'):
238
+ display.deprecated(
239
+ "Using 'yes' or 'no' for 'follow_redirects' parameter is deprecated.",
240
+ version='2.22'
241
+ )
237
242
  try:
238
243
  response = open_url(
239
244
  term, validate_certs=self.get_option('validate_certs'),
@@ -18,8 +18,8 @@ from __future__ import annotations
18
18
 
19
19
  import os
20
20
  import os.path
21
- import random
22
21
  import re
22
+ import secrets
23
23
  import shlex
24
24
  import time
25
25
 
@@ -38,6 +38,9 @@ class ShellBase(AnsiblePlugin):
38
38
 
39
39
  super(ShellBase, self).__init__()
40
40
 
41
+ # Not used but here for backwards compatibility.
42
+ # ansible.posix.fish uses (but does not actually use) this value.
43
+ # https://github.com/ansible-collections/ansible.posix/blob/f41f08e9e3d3129e709e122540b5ae6bc19932be/plugins/shell/fish.py#L38-L39
41
44
  self.env = {}
42
45
  self.tmpdir = None
43
46
  self.executable = None
@@ -60,18 +63,6 @@ class ShellBase(AnsiblePlugin):
60
63
 
61
64
  super(ShellBase, self).set_options(task_keys=task_keys, var_options=var_options, direct=direct)
62
65
 
63
- # set env if needed, deal with environment's 'dual nature' list of dicts or dict
64
- # TODO: config system should already resolve this so we should be able to just iterate over dicts
65
- env = self.get_option('environment')
66
- if isinstance(env, string_types):
67
- raise AnsibleError('The "environment" keyword takes a list of dictionaries or a dictionary, not a string')
68
- if not isinstance(env, Sequence):
69
- env = [env]
70
- for env_dict in env:
71
- if not isinstance(env_dict, Mapping):
72
- raise AnsibleError('The "environment" keyword takes a list of dictionaries (or single dictionary), but got a "%s" instead' % type(env_dict))
73
- self.env.update(env_dict)
74
-
75
66
  # We can remove the try: except in the future when we make ShellBase a proper subset of
76
67
  # *all* shells. Right now powershell and third party shells which do not use the
77
68
  # shell_common documentation fragment (and so do not have system_tmpdirs) will fail
@@ -82,7 +73,7 @@ class ShellBase(AnsiblePlugin):
82
73
 
83
74
  @staticmethod
84
75
  def _generate_temp_dir_name():
85
- return 'ansible-tmp-%s-%s-%s' % (time.time(), os.getpid(), random.randint(0, 2**48))
76
+ return 'ansible-tmp-%s-%s-%s' % (time.time(), os.getpid(), secrets.randbelow(2**48))
86
77
 
87
78
  def env_prefix(self, **kwargs):
88
79
  return ' '.join(['%s=%s' % (k, self.quote(text_type(v))) for k, v in kwargs.items()])
@@ -101,23 +92,23 @@ class ShellBase(AnsiblePlugin):
101
92
  def chmod(self, paths, mode):
102
93
  cmd = ['chmod', mode]
103
94
  cmd.extend(paths)
104
- return shlex.join(cmd)
95
+ return self.join(cmd)
105
96
 
106
97
  def chown(self, paths, user):
107
98
  cmd = ['chown', user]
108
99
  cmd.extend(paths)
109
- return shlex.join(cmd)
100
+ return self.join(cmd)
110
101
 
111
102
  def chgrp(self, paths, group):
112
103
  cmd = ['chgrp', group]
113
104
  cmd.extend(paths)
114
- return shlex.join(cmd)
105
+ return self.join(cmd)
115
106
 
116
107
  def set_user_facl(self, paths, user, mode):
117
108
  """Only sets acls for users as that's really all we need"""
118
109
  cmd = ['setfacl', '-m', 'u:%s:%s' % (user, mode)]
119
110
  cmd.extend(paths)
120
- return shlex.join(cmd)
111
+ return self.join(cmd)
121
112
 
122
113
  def remove(self, path, recurse=False):
123
114
  path = self.quote(path)
@@ -138,7 +129,7 @@ class ShellBase(AnsiblePlugin):
138
129
  # other users can read and access the tmp directory.
139
130
  # This is because we use system to create tmp dirs for unprivileged users who are
140
131
  # sudo'ing to a second unprivileged user.
141
- # The 'system_tmpdirs' setting defines dirctories we can use for this purpose
132
+ # The 'system_tmpdirs' setting defines directories we can use for this purpose
142
133
  # the default are, /tmp and /var/tmp.
143
134
  # So we only allow one of those locations if system=True, using the
144
135
  # passed in tmpdir if it is valid or the first one from the setting if not.
@@ -211,7 +202,7 @@ class ShellBase(AnsiblePlugin):
211
202
  arg_path,
212
203
  ]
213
204
 
214
- cleaned_up_cmd = shlex.join(
205
+ cleaned_up_cmd = self.join(
215
206
  stripped_cmd_part for raw_cmd_part in cmd_parts
216
207
  if raw_cmd_part and (stripped_cmd_part := raw_cmd_part.strip())
217
208
  )
@@ -232,3 +223,7 @@ class ShellBase(AnsiblePlugin):
232
223
  def quote(self, cmd):
233
224
  """Returns a shell-escaped string that can be safely used as one token in a shell command line"""
234
225
  return shlex.quote(cmd)
226
+
227
+ def join(self, cmd_parts):
228
+ """Returns a shell-escaped string from a list that can be safely used in a shell command line"""
229
+ return shlex.join(cmd_parts)
@@ -100,6 +100,8 @@ class ShellModule(ShellBase):
100
100
  # Family of shells this has. Must match the filename without extension
101
101
  SHELL_FAMILY = 'powershell'
102
102
 
103
+ # We try catch as some connection plugins don't have a console (PSRP).
104
+ _CONSOLE_ENCODING = "try { [Console]::OutputEncoding = New-Object System.Text.UTF8Encoding } catch {}"
103
105
  _SHELL_REDIRECT_ALLNULL = '> $null'
104
106
  _SHELL_AND = ';'
105
107
 
@@ -157,13 +159,14 @@ class ShellModule(ShellBase):
157
159
  if not basefile:
158
160
  basefile = self.__class__._generate_temp_dir_name()
159
161
  basefile = self._escape(self._unquote(basefile))
160
- basetmpdir = tmpdir if tmpdir else self.get_option('remote_tmp')
162
+ basetmpdir = self._escape(tmpdir if tmpdir else self.get_option('remote_tmp'))
161
163
 
162
- script = '''
163
- $tmp_path = [System.Environment]::ExpandEnvironmentVariables('%s')
164
- $tmp = New-Item -Type Directory -Path $tmp_path -Name '%s'
164
+ script = f'''
165
+ {self._CONSOLE_ENCODING}
166
+ $tmp_path = [System.Environment]::ExpandEnvironmentVariables('{basetmpdir}')
167
+ $tmp = New-Item -Type Directory -Path $tmp_path -Name '{basefile}'
165
168
  Write-Output -InputObject $tmp.FullName
166
- ''' % (basetmpdir, basefile)
169
+ '''
167
170
  return self._encode_script(script.strip())
168
171
 
169
172
  def expand_user(self, user_home_path, username=''):
@@ -177,7 +180,7 @@ class ShellModule(ShellBase):
177
180
  script = "Write-Output ((Get-Location).Path + '%s')" % self._escape(user_home_path[1:])
178
181
  else:
179
182
  script = "Write-Output '%s'" % self._escape(user_home_path)
180
- return self._encode_script(script)
183
+ return self._encode_script(f"{self._CONSOLE_ENCODING}; {script}")
181
184
 
182
185
  def exists(self, path):
183
186
  path = self._escape(self._unquote(path))
@@ -646,7 +646,7 @@ class StrategyBase:
646
646
  for result_item in result_items:
647
647
  if '_ansible_notify' in result_item and task_result.is_changed():
648
648
  # only ensure that notified handlers exist, if so save the notifications for when
649
- # handlers are actually flushed so the last defined handlers are exexcuted,
649
+ # handlers are actually flushed so the last defined handlers are executed,
650
650
  # otherwise depending on the setting either error or warn
651
651
  host_state = iterator.get_state_for_host(original_host.name)
652
652
  for notification in result_item['_ansible_notify']:
@@ -995,7 +995,7 @@ class StrategyBase:
995
995
  if _evaluate_conditional(target_host):
996
996
  for host in self._inventory.get_hosts(iterator._play.hosts):
997
997
  if host.name not in self._tqm._unreachable_hosts:
998
- iterator.set_run_state_for_host(host.name, IteratingStates.COMPLETE)
998
+ iterator.end_host(host.name)
999
999
  msg = "ending batch"
1000
1000
  else:
1001
1001
  skipped = True
@@ -1004,7 +1004,7 @@ class StrategyBase:
1004
1004
  if _evaluate_conditional(target_host):
1005
1005
  for host in self._inventory.get_hosts(iterator._play.hosts):
1006
1006
  if host.name not in self._tqm._unreachable_hosts:
1007
- iterator.set_run_state_for_host(host.name, IteratingStates.COMPLETE)
1007
+ iterator.end_host(host.name)
1008
1008
  # end_play is used in PlaybookExecutor/TQM to indicate that
1009
1009
  # the whole play is supposed to be ended as opposed to just a batch
1010
1010
  iterator.end_play = True
@@ -1014,8 +1014,7 @@ class StrategyBase:
1014
1014
  skip_reason += ', continuing play'
1015
1015
  elif meta_action == 'end_host':
1016
1016
  if _evaluate_conditional(target_host):
1017
- iterator.set_run_state_for_host(target_host.name, IteratingStates.COMPLETE)
1018
- iterator._play._removed_hosts.append(target_host.name)
1017
+ iterator.end_host(target_host.name)
1019
1018
  msg = "ending play for %s" % target_host.name
1020
1019
  else:
1021
1020
  skipped = True
@@ -1023,13 +1022,23 @@ class StrategyBase:
1023
1022
  # TODO: Nix msg here? Left for historical reasons, but skip_reason exists now.
1024
1023
  msg = "end_host conditional evaluated to false, continuing execution for %s" % target_host.name
1025
1024
  elif meta_action == 'role_complete':
1026
- # Allow users to use this in a play as reported in https://github.com/ansible/ansible/issues/22286?
1027
- # How would this work with allow_duplicates??
1028
1025
  if task.implicit:
1029
1026
  role_obj = self._get_cached_role(task, iterator._play)
1030
1027
  if target_host.name in role_obj._had_task_run:
1031
1028
  role_obj._completed[target_host.name] = True
1032
1029
  msg = 'role_complete for %s' % target_host.name
1030
+ elif meta_action == 'end_role':
1031
+ if _evaluate_conditional(target_host):
1032
+ while True:
1033
+ state, task = iterator.get_next_task_for_host(target_host, peek=True)
1034
+ if task.action in C._ACTION_META and task.args.get("_raw_params") == "role_complete":
1035
+ break
1036
+ iterator.set_state_for_host(target_host.name, state)
1037
+ display.debug("'%s' skipped because role has been ended via 'end_role'" % task)
1038
+ msg = 'ending role %s for %s' % (task._role.get_name(), target_host.name)
1039
+ else:
1040
+ skipped = True
1041
+ skip_reason += 'continuing role %s for %s' % (task._role.get_name(), target_host.name)
1033
1042
  elif meta_action == 'reset_connection':
1034
1043
  all_vars = self._variable_manager.get_vars(play=iterator._play, host=target_host, task=task,
1035
1044
  _hosts=self._hosts_cache, _hosts_all=self._hosts_cache_all)
@@ -25,8 +25,9 @@ from collections.abc import MutableMapping, MutableSequence
25
25
  from ansible.module_utils.compat.version import LooseVersion, StrictVersion
26
26
 
27
27
  from ansible import errors
28
- from ansible.module_utils.common.text.converters import to_native, to_text
28
+ from ansible.module_utils.common.text.converters import to_native, to_text, to_bytes
29
29
  from ansible.module_utils.parsing.convert_bool import boolean
30
+ from ansible.parsing.vault import is_encrypted_file
30
31
  from ansible.utils.display import Display
31
32
  from ansible.utils.version import SemanticVersion
32
33
 
@@ -39,6 +40,13 @@ except ImportError:
39
40
  display = Display()
40
41
 
41
42
 
43
+ def timedout(result):
44
+ ''' Test if task result yields a time out'''
45
+ if not isinstance(result, MutableMapping):
46
+ raise errors.AnsibleFilterError("The 'timedout' test expects a dictionary")
47
+ return result.get('timedout', False) and result['timedout'].get('period', False)
48
+
49
+
42
50
  def failed(result):
43
51
  ''' Test if task result yields failed '''
44
52
  if not isinstance(result, MutableMapping):
@@ -143,6 +151,18 @@ def vault_encrypted(value):
143
151
  return getattr(value, '__ENCRYPTED__', False) and value.is_encrypted()
144
152
 
145
153
 
154
+ def vaulted_file(value):
155
+ """Evaluate whether a file is a vault
156
+
157
+ .. versionadded:: 2.18
158
+ """
159
+ try:
160
+ with open(to_bytes(value), 'rb') as f:
161
+ return is_encrypted_file(f)
162
+ except (OSError, IOError) as e:
163
+ raise errors.AnsibleFilterError(f"Cannot test if the file {value} is a vault", orig_exc=e)
164
+
165
+
146
166
  def match(value, pattern='', ignorecase=False, multiline=False):
147
167
  ''' Perform a `re.match` returning a boolean '''
148
168
  return regex(value, pattern, ignorecase, multiline, 'match')
@@ -250,6 +270,7 @@ class TestModule(object):
250
270
  'successful': success,
251
271
  'reachable': reachable,
252
272
  'unreachable': unreachable,
273
+ 'timedout': timedout,
253
274
 
254
275
  # changed testing
255
276
  'changed': changed,
@@ -282,4 +303,5 @@ class TestModule(object):
282
303
 
283
304
  # vault
284
305
  'vault_encrypted': vault_encrypted,
306
+ 'vaulted_file': vaulted_file,
285
307
  }
@@ -19,7 +19,7 @@ DOCUMENTATION:
19
19
  required: True
20
20
  EXAMPLES: |
21
21
  big: [1,2,3,4,5]
22
- sml: [3,4]
22
+ small: [3,4]
23
23
  issmallinbig: '{{ small is subset(big) }}'
24
24
  RETURN:
25
25
  _value:
@@ -19,7 +19,7 @@ DOCUMENTATION:
19
19
  required: True
20
20
  EXAMPLES: |
21
21
  big: [1,2,3,4,5]
22
- sml: [3,4]
22
+ small: [3,4]
23
23
  issmallinbig: '{{ small is subset(big) }}'
24
24
  RETURN:
25
25
  _value:
@@ -0,0 +1,20 @@
1
+ DOCUMENTATION:
2
+ name: timedout
3
+ author: Ansible Core
4
+ version_added: "2.18"
5
+ short_description: did the task time out
6
+ description:
7
+ - Tests if task finished ended due to a time out
8
+ options:
9
+ _input:
10
+ description: registered result from an Ansible task
11
+ type: dictionary
12
+ required: True
13
+ EXAMPLES: |
14
+ # test 'status' to know how to respond
15
+ {{ taskresults is timedout }}
16
+
17
+ RETURN:
18
+ _value:
19
+ description: A dictionary with 2 keys 'frame' showing the 'frame of code' in which the timeout occurred and 'period' with the time limit that was enforced.
20
+ type: dict
@@ -1,18 +1,18 @@
1
1
  DOCUMENTATION:
2
- name: truthy
2
+ name: vault_encrypted
3
3
  author: Ansible Core
4
4
  version_added: "2.10"
5
- short_description: Is this an encrypted vault
5
+ short_description: Is this an encrypted vault string
6
6
  description:
7
- - Verifies if the input is an Ansible vault.
7
+ - Verifies if the input string is an Ansible vault or not
8
8
  options:
9
9
  _input:
10
- description: The possible vault.
10
+ description: The possible vault string
11
11
  type: string
12
12
  required: True
13
13
  EXAMPLES: |
14
- thisisfalse: '{{ "any string" is ansible_vault }}'
15
- thisistrue: '{{ "$ANSIBLE_VAULT;1.2;AES256;dev...." is ansible_vault }}'
14
+ thisisfalse: '{{ "any string" is vault_encryped}}'
15
+ thisistrue: '{{ "$ANSIBLE_VAULT;1.2;AES256;dev...." is vault_encrypted}}'
16
16
  RETURN:
17
17
  _value:
18
18
  description: Returns V(True) if the input is a valid ansible vault, V(False) otherwise.
@@ -0,0 +1,19 @@
1
+ DOCUMENTATION:
2
+ name: vaulted_file
3
+ author: Ansible Core
4
+ version_added: "2.18"
5
+ short_description: Is this file an encrypted vault
6
+ description:
7
+ - Verifies if the input path is an Ansible vault file.
8
+ options:
9
+ _input:
10
+ description: The path to the possible vault.
11
+ type: path
12
+ required: True
13
+ EXAMPLES: |
14
+ thisisfalse: '{{ "/etc/hosts" is vaulted_file}}'
15
+ thisistrue: '{{ "/path/to/vaulted/file" is vaulted_file}}'
16
+ RETURN:
17
+ _value:
18
+ description: Returns V(True) if the path is a valid ansible vault, V(False) otherwise.
19
+ type: boolean
ansible/release.py CHANGED
@@ -17,6 +17,6 @@
17
17
 
18
18
  from __future__ import annotations
19
19
 
20
- __version__ = '2.17.6'
20
+ __version__ = '2.18.0'
21
21
  __author__ = 'Ansible, Inc.'
22
- __codename__ = "Gallows Pole"
22
+ __codename__ = "Fool in the Rain"
@@ -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: