ansible-core 2.17.6rc1__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.6rc1.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.6rc1.dist-info → ansible_core-2.18.0.dist-info}/RECORD +316 -311
  255. {ansible_core-2.17.6rc1.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.6rc1.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.6rc1.dist-info → ansible_core-2.18.0.dist-info}/COPYING +0 -0
  324. {ansible_core-2.17.6rc1.dist-info → ansible_core-2.18.0.dist-info}/WHEEL +0 -0
  325. {ansible_core-2.17.6rc1.dist-info → ansible_core-2.18.0.dist-info}/top_level.txt +0 -0
@@ -8,7 +8,7 @@ import errno
8
8
  import json
9
9
  import os
10
10
  import pkgutil
11
- import random
11
+ import secrets
12
12
  import re
13
13
  from importlib import import_module
14
14
 
@@ -318,7 +318,7 @@ def _create_powershell_wrapper(b_module_data, module_path, module_args,
318
318
 
319
319
  exec_manifest["actions"].insert(0, 'async_watchdog')
320
320
  exec_manifest["actions"].insert(0, 'async_wrapper')
321
- exec_manifest["async_jid"] = f'j{random.randint(0, 999999999999)}'
321
+ exec_manifest["async_jid"] = f'j{secrets.randbelow(999999999999)}'
322
322
  exec_manifest["async_timeout_sec"] = async_timeout
323
323
  exec_manifest["async_startup_timeout"] = C.config.get_config_value("WIN_ASYNC_STARTUP_TIMEOUT", variables=task_vars)
324
324
 
@@ -4,23 +4,24 @@
4
4
  from __future__ import annotations
5
5
 
6
6
  import os
7
- import pty
8
7
  import time
9
8
  import json
9
+ import pathlib
10
10
  import signal
11
11
  import subprocess
12
12
  import sys
13
- import termios
14
13
  import traceback
15
14
 
16
15
  from ansible import constants as C
16
+ from ansible.cli import scripts
17
17
  from ansible.errors import AnsibleError, AnsibleParserError, AnsibleUndefinedVariable, AnsibleConnectionFailure, AnsibleActionFail, AnsibleActionSkip
18
18
  from ansible.executor.task_result import TaskResult
19
19
  from ansible.executor.module_common import get_action_args_with_defaults
20
20
  from ansible.module_utils.parsing.convert_bool import boolean
21
21
  from ansible.module_utils.six import binary_type
22
22
  from ansible.module_utils.common.text.converters import to_text, to_native
23
- from ansible.module_utils.connection import write_to_file_descriptor
23
+ from ansible.module_utils.connection import write_to_stream
24
+ from ansible.module_utils.six import string_types
24
25
  from ansible.playbook.conditional import Conditional
25
26
  from ansible.playbook.task import Task
26
27
  from ansible.plugins import get_plugin_class
@@ -42,11 +43,21 @@ __all__ = ['TaskExecutor']
42
43
 
43
44
 
44
45
  class TaskTimeoutError(BaseException):
45
- pass
46
+ def __init__(self, message="", frame=None):
47
+
48
+ if frame is not None:
49
+ orig = frame
50
+ root = pathlib.Path(__file__).parent
51
+ while not pathlib.Path(frame.f_code.co_filename).is_relative_to(root):
52
+ frame = frame.f_back
53
+
54
+ self.frame = 'Interrupted at %s called from %s' % (orig, frame)
55
+
56
+ super(TaskTimeoutError, self).__init__(message)
46
57
 
47
58
 
48
59
  def task_timeout(signum, frame):
49
- raise TaskTimeoutError
60
+ raise TaskTimeoutError(frame=frame)
50
61
 
51
62
 
52
63
  def remove_omit(task_args, omit_token):
@@ -369,12 +380,17 @@ class TaskExecutor:
369
380
  'msg': 'Failed to template loop_control.label: %s' % to_text(e)
370
381
  })
371
382
 
383
+ # if plugin is loaded, get resolved name, otherwise leave original task connection
384
+ if self._connection and not isinstance(self._connection, string_types):
385
+ task_fields['connection'] = getattr(self._connection, 'ansible_name')
386
+
372
387
  tr = TaskResult(
373
388
  self._host.name,
374
389
  self._task._uuid,
375
390
  res,
376
391
  task_fields=task_fields,
377
392
  )
393
+
378
394
  if tr.is_failed() or tr.is_unreachable():
379
395
  self._final_q.send_callback('v2_runner_item_on_failed', tr)
380
396
  elif tr.is_skipped():
@@ -386,6 +402,19 @@ class TaskExecutor:
386
402
  self._final_q.send_callback('v2_runner_item_on_ok', tr)
387
403
 
388
404
  results.append(res)
405
+
406
+ # break loop if break_when conditions are met
407
+ if self._task.loop_control and self._task.loop_control.break_when:
408
+ cond = Conditional(loader=self._loader)
409
+ cond.when = self._task.loop_control.get_validated_value(
410
+ 'break_when', self._task.loop_control.fattributes.get('break_when'), self._task.loop_control.break_when, templar
411
+ )
412
+ if cond.evaluate_conditional(templar, task_vars):
413
+ # delete loop vars before exiting loop
414
+ del task_vars[loop_var]
415
+ break
416
+
417
+ # done with loop var, remove for next iteration
389
418
  del task_vars[loop_var]
390
419
 
391
420
  # clear 'connection related' plugin variables for next iteration
@@ -647,7 +676,7 @@ class TaskExecutor:
647
676
  return dict(unreachable=True, msg=to_text(e))
648
677
  except TaskTimeoutError as e:
649
678
  msg = 'The %s action failed to execute in the expected time frame (%d) and was terminated' % (self._task.action, self._task.timeout)
650
- return dict(failed=True, msg=msg)
679
+ return dict(failed=True, msg=msg, timedout={'frame': e.frame, 'period': self._task.timeout})
651
680
  finally:
652
681
  if self._task.timeout:
653
682
  signal.alarm(0)
@@ -1183,26 +1212,19 @@ class TaskExecutor:
1183
1212
  return handler, module
1184
1213
 
1185
1214
 
1215
+ CLI_STUB_NAME = 'ansible_connection_cli_stub.py'
1216
+
1217
+
1186
1218
  def start_connection(play_context, options, task_uuid):
1187
1219
  '''
1188
1220
  Starts the persistent connection
1189
1221
  '''
1190
- candidate_paths = [C.ANSIBLE_CONNECTION_PATH or os.path.dirname(sys.argv[0])]
1191
- candidate_paths.extend(os.environ.get('PATH', '').split(os.pathsep))
1192
- for dirname in candidate_paths:
1193
- ansible_connection = os.path.join(dirname, 'ansible-connection')
1194
- if os.path.isfile(ansible_connection):
1195
- display.vvvv("Found ansible-connection at path {0}".format(ansible_connection))
1196
- break
1197
- else:
1198
- raise AnsibleError("Unable to find location of 'ansible-connection'. "
1199
- "Please set or check the value of ANSIBLE_CONNECTION_PATH")
1200
1222
 
1201
1223
  env = os.environ.copy()
1202
1224
  env.update({
1203
1225
  # HACK; most of these paths may change during the controller's lifetime
1204
1226
  # (eg, due to late dynamic role includes, multi-playbook execution), without a way
1205
- # to invalidate/update, ansible-connection won't always see the same plugins the controller
1227
+ # to invalidate/update, the persistent connection helper won't always see the same plugins the controller
1206
1228
  # can.
1207
1229
  'ANSIBLE_BECOME_PLUGINS': become_loader.print_paths(),
1208
1230
  'ANSIBLE_CLICONF_PLUGINS': cliconf_loader.print_paths(),
@@ -1215,30 +1237,19 @@ def start_connection(play_context, options, task_uuid):
1215
1237
  verbosity = []
1216
1238
  if display.verbosity:
1217
1239
  verbosity.append('-%s' % ('v' * display.verbosity))
1218
- python = sys.executable
1219
- master, slave = pty.openpty()
1240
+
1241
+ if not (cli_stub_path := C.config.get_config_value('_ANSIBLE_CONNECTION_PATH')):
1242
+ cli_stub_path = str(pathlib.Path(scripts.__file__).parent / CLI_STUB_NAME)
1243
+
1220
1244
  p = subprocess.Popen(
1221
- [python, ansible_connection, *verbosity, to_text(os.getppid()), to_text(task_uuid)],
1222
- stdin=slave, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env
1245
+ [sys.executable, cli_stub_path, *verbosity, to_text(os.getppid()), to_text(task_uuid)],
1246
+ stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env,
1223
1247
  )
1224
- os.close(slave)
1225
-
1226
- # We need to set the pty into noncanonical mode. This ensures that we
1227
- # can receive lines longer than 4095 characters (plus newline) without
1228
- # truncating.
1229
- old = termios.tcgetattr(master)
1230
- new = termios.tcgetattr(master)
1231
- new[3] = new[3] & ~termios.ICANON
1232
-
1233
- try:
1234
- termios.tcsetattr(master, termios.TCSANOW, new)
1235
- write_to_file_descriptor(master, options)
1236
- write_to_file_descriptor(master, play_context.serialize())
1237
-
1238
- (stdout, stderr) = p.communicate()
1239
- finally:
1240
- termios.tcsetattr(master, termios.TCSANOW, old)
1241
- os.close(master)
1248
+
1249
+ write_to_stream(p.stdin, options)
1250
+ write_to_stream(p.stdin, play_context.serialize())
1251
+
1252
+ (stdout, stderr) = p.communicate()
1242
1253
 
1243
1254
  if p.returncode == 0:
1244
1255
  result = json.loads(to_text(stdout, errors='surrogate_then_replace'))
@@ -223,7 +223,7 @@ class TaskQueueManager:
223
223
  callback_type = getattr(callback_plugin, 'CALLBACK_TYPE', '')
224
224
  callback_needs_enabled = getattr(callback_plugin, 'CALLBACK_NEEDS_ENABLED', getattr(callback_plugin, 'CALLBACK_NEEDS_WHITELIST', False))
225
225
 
226
- # try to get colleciotn world name first
226
+ # try to get collection world name first
227
227
  cnames = getattr(callback_plugin, '_redirected_names', [])
228
228
  if cnames:
229
229
  # store the name the plugin was loaded as, as that's what we'll need to compare to the configured callback list later
@@ -139,7 +139,7 @@ class TaskResult:
139
139
  elif self._result:
140
140
  result._result = module_response_deepcopy(self._result)
141
141
 
142
- # actualy remove
142
+ # actually remove
143
143
  for remove_key in ignore:
144
144
  if remove_key in result._result:
145
145
  del result._result[remove_key]
ansible/galaxy/api.py CHANGED
@@ -62,8 +62,7 @@ def should_retry_error(exception):
62
62
  if isinstance(orig_exc, URLError):
63
63
  orig_exc = orig_exc.reason
64
64
 
65
- # Handle common URL related errors such as TimeoutError, and BadStatusLine
66
- # Note: socket.timeout is only required for Py3.9
65
+ # Handle common URL related errors
67
66
  if isinstance(orig_exc, (TimeoutError, BadStatusLine, IncompleteRead)):
68
67
  return True
69
68
 
@@ -720,7 +719,7 @@ class GalaxyAPI:
720
719
 
721
720
  display.display("Waiting until Galaxy import task %s has completed" % full_url)
722
721
  start = time.time()
723
- wait = 2
722
+ wait = C.GALAXY_COLLECTION_IMPORT_POLL_INTERVAL
724
723
 
725
724
  while timeout == 0 or (time.time() - start) < timeout:
726
725
  try:
@@ -744,7 +743,7 @@ class GalaxyAPI:
744
743
  time.sleep(wait)
745
744
 
746
745
  # poor man's exponential backoff algo so we don't flood the Galaxy API, cap at 30 seconds.
747
- wait = min(30, wait * 1.5)
746
+ wait = min(30, wait * C.GALAXY_COLLECTION_IMPORT_POLL_FACTOR)
748
747
  if state == 'waiting':
749
748
  raise AnsibleError("Timeout while waiting for the Galaxy import process to finish, check progress at '%s'"
750
749
  % to_native(full_url))
@@ -8,6 +8,7 @@ from __future__ import annotations
8
8
  import errno
9
9
  import fnmatch
10
10
  import functools
11
+ import glob
11
12
  import inspect
12
13
  import json
13
14
  import os
@@ -1525,6 +1526,7 @@ def install(collection, path, artifacts_manager): # FIXME: mv to dataclasses?
1525
1526
  artifacts_manager.required_successful_signature_count,
1526
1527
  artifacts_manager.ignore_signature_errors,
1527
1528
  )
1529
+ remove_source_metadata(collection, b_collection_path)
1528
1530
  if (collection.is_online_index_pointer and isinstance(collection.src, GalaxyAPI)):
1529
1531
  write_source_metadata(
1530
1532
  collection,
@@ -1561,6 +1563,22 @@ def write_source_metadata(collection, b_collection_path, artifacts_manager):
1561
1563
  raise
1562
1564
 
1563
1565
 
1566
+ def remove_source_metadata(collection, b_collection_path):
1567
+ pattern = f"{collection.namespace}.{collection.name}-*.info"
1568
+ info_path = os.path.join(
1569
+ b_collection_path,
1570
+ b'../../',
1571
+ to_bytes(pattern, errors='surrogate_or_strict')
1572
+ )
1573
+ if (outdated_info := glob.glob(info_path)):
1574
+ display.vvvv(f"Removing {pattern} metadata from previous installations")
1575
+ for info_dir in outdated_info:
1576
+ try:
1577
+ shutil.rmtree(info_dir)
1578
+ except Exception:
1579
+ pass
1580
+
1581
+
1564
1582
  def verify_artifact_manifest(manifest_file, signatures, keyring, required_signature_count, ignore_signature_errors):
1565
1583
  # type: (str, list[str], str, str, list[str]) -> None
1566
1584
  failed_verify = False
@@ -1584,13 +1602,6 @@ def install_artifact(b_coll_targz_path, b_collection_path, b_temp_path, signatur
1584
1602
  """
1585
1603
  try:
1586
1604
  with tarfile.open(b_coll_targz_path, mode='r') as collection_tar:
1587
- # Remove this once py3.11 is our controller minimum
1588
- # Workaround for https://bugs.python.org/issue47231
1589
- # See _extract_tar_dir
1590
- collection_tar._ansible_normalized_cache = {
1591
- m.name.removesuffix(os.path.sep): m for m in collection_tar.getmembers()
1592
- } # deprecated: description='TarFile member index' core_version='2.18' python_version='3.11'
1593
-
1594
1605
  # Verify the signature on the MANIFEST.json before extracting anything else
1595
1606
  _extract_tar_file(collection_tar, MANIFEST_FILENAME, b_collection_path, b_temp_path)
1596
1607
 
@@ -1671,10 +1682,10 @@ def install_src(collection, b_collection_path, b_collection_output_path, artifac
1671
1682
 
1672
1683
  def _extract_tar_dir(tar, dirname, b_dest):
1673
1684
  """ Extracts a directory from a collection tar. """
1674
- dirname = to_native(dirname, errors='surrogate_or_strict').removesuffix(os.path.sep)
1685
+ dirname = to_native(dirname, errors='surrogate_or_strict')
1675
1686
 
1676
1687
  try:
1677
- tar_member = tar._ansible_normalized_cache[dirname]
1688
+ tar_member = tar.getmember(dirname)
1678
1689
  except KeyError:
1679
1690
  raise AnsibleError("Unable to extract '%s' from collection" % dirname)
1680
1691
 
@@ -1896,7 +1907,7 @@ def _resolve_depenency_map(
1896
1907
 
1897
1908
  for req in dep_exc.criterion.iter_requirement():
1898
1909
  error_msg_lines.append(
1899
- '* {req.fqcn!s}:{req.ver!s}'.format(req=req)
1910
+ f'* {req.fqcn!s}:{req.ver!s}'
1900
1911
  )
1901
1912
  error_msg_lines.append(pre_release_hint)
1902
1913
 
@@ -63,7 +63,7 @@ class ConcreteArtifactsManager:
63
63
  """
64
64
  def __init__(self, b_working_directory, validate_certs=True, keyring=None, timeout=60, required_signature_count=None, ignore_signature_errors=None):
65
65
  # type: (bytes, bool, str, int, str, list[str]) -> None
66
- """Initialize ConcreteArtifactsManager caches and costraints."""
66
+ """Initialize ConcreteArtifactsManager caches and constraints."""
67
67
  self._validate_certs = validate_certs # type: bool
68
68
  self._artifact_cache = {} # type: dict[bytes, bytes]
69
69
  self._galaxy_artifact_cache = {} # type: dict[Candidate | Requirement, bytes]
@@ -415,7 +415,7 @@ def _extract_collection_from_git(repo_url, coll_ver, b_path):
415
415
  b_checkout_path = mkdtemp(
416
416
  dir=b_path,
417
417
  prefix=to_bytes(name, errors='surrogate_or_strict'),
418
- ) # type: bytes
418
+ )
419
419
 
420
420
  try:
421
421
  git_executable = get_bin_path('git')
@@ -27,8 +27,7 @@ display = Display()
27
27
  class MultiGalaxyAPIProxy:
28
28
  """A proxy that abstracts talking to multiple Galaxy instances."""
29
29
 
30
- def __init__(self, apis, concrete_artifacts_manager, offline=False):
31
- # type: (t.Iterable[GalaxyAPI], ConcreteArtifactsManager, bool) -> None
30
+ def __init__(self, apis: t.Iterable[GalaxyAPI], concrete_artifacts_manager: ConcreteArtifactsManager, offline: bool = False) -> None:
32
31
  """Initialize the target APIs list."""
33
32
  self._apis = apis
34
33
  self._concrete_art_mgr = concrete_artifacts_manager
@@ -38,22 +37,21 @@ class MultiGalaxyAPIProxy:
38
37
  def is_offline_mode_requested(self):
39
38
  return self._offline
40
39
 
41
- def _assert_that_offline_mode_is_not_requested(self): # type: () -> None
40
+ def _assert_that_offline_mode_is_not_requested(self) -> None:
42
41
  if self.is_offline_mode_requested:
43
42
  raise NotImplementedError("The calling code is not supposed to be invoked in 'offline' mode.")
44
43
 
45
- def _get_collection_versions(self, requirement):
46
- # type: (Requirement) -> t.Iterator[tuple[GalaxyAPI, str]]
44
+ def _get_collection_versions(self, requirement: Requirement) -> t.Iterator[tuple[GalaxyAPI, str]]:
47
45
  """Helper for get_collection_versions.
48
46
 
49
47
  Yield api, version pairs for all APIs,
50
48
  and reraise the last error if no valid API was found.
51
49
  """
52
50
  if self._offline:
53
- return []
51
+ return
54
52
 
55
53
  found_api = False
56
- last_error = None # type: Exception | None
54
+ last_error: Exception | None = None
57
55
 
58
56
  api_lookup_order = (
59
57
  (requirement.src, )
@@ -86,8 +84,7 @@ class MultiGalaxyAPIProxy:
86
84
  if not found_api and last_error is not None:
87
85
  raise last_error
88
86
 
89
- def get_collection_versions(self, requirement):
90
- # type: (Requirement) -> t.Iterable[tuple[str, GalaxyAPI]]
87
+ def get_collection_versions(self, requirement: Requirement) -> t.Iterable[tuple[str, GalaxyAPI]]:
91
88
  """Get a set of unique versions for FQCN on Galaxy servers."""
92
89
  if requirement.is_concrete_artifact:
93
90
  return {
@@ -110,8 +107,7 @@ class MultiGalaxyAPIProxy:
110
107
  )
111
108
  )
112
109
 
113
- def get_collection_version_metadata(self, collection_candidate):
114
- # type: (Candidate) -> CollectionVersionMetadata
110
+ def get_collection_version_metadata(self, collection_candidate: Candidate) -> CollectionVersionMetadata:
115
111
  """Retrieve collection metadata of a given candidate."""
116
112
  self._assert_that_offline_mode_is_not_requested()
117
113
 
@@ -160,8 +156,7 @@ class MultiGalaxyAPIProxy:
160
156
 
161
157
  raise last_err
162
158
 
163
- def get_collection_dependencies(self, collection_candidate):
164
- # type: (Candidate) -> dict[str, str]
159
+ def get_collection_dependencies(self, collection_candidate: Candidate) -> dict[str, str]:
165
160
  # FIXME: return Requirement instances instead?
166
161
  """Retrieve collection dependencies of a given candidate."""
167
162
  if collection_candidate.is_concrete_artifact:
@@ -177,13 +172,12 @@ class MultiGalaxyAPIProxy:
177
172
  dependencies
178
173
  )
179
174
 
180
- def get_signatures(self, collection_candidate):
181
- # type: (Candidate) -> list[str]
175
+ def get_signatures(self, collection_candidate: Candidate) -> list[str]:
182
176
  self._assert_that_offline_mode_is_not_requested()
183
177
  namespace = collection_candidate.namespace
184
178
  name = collection_candidate.name
185
179
  version = collection_candidate.ver
186
- last_err = None # type: Exception | None
180
+ last_err: Exception | None = None
187
181
 
188
182
  api_lookup_order = (
189
183
  (collection_candidate.src, )
@@ -12,20 +12,14 @@ import contextlib
12
12
  import inspect
13
13
  import os
14
14
  import subprocess
15
- import sys
16
15
  import typing as t
17
16
 
18
17
  from dataclasses import dataclass, fields as dc_fields
19
- from functools import partial
20
18
  from urllib.error import HTTPError, URLError
21
19
 
22
20
  if t.TYPE_CHECKING:
23
21
  from ansible.utils.display import Display
24
22
 
25
- IS_PY310_PLUS = sys.version_info[:2] >= (3, 10)
26
-
27
- frozen_dataclass = partial(dataclass, frozen=True, **({'slots': True} if IS_PY310_PLUS else {}))
28
-
29
23
 
30
24
  def get_signature_from_source(source, display=None): # type: (str, t.Optional[Display]) -> str
31
25
  if display is not None:
@@ -128,7 +122,7 @@ def parse_gpg_errors(status_out): # type: (str) -> t.Iterator[GpgBaseError]
128
122
  yield cls(*fields)
129
123
 
130
124
 
131
- @frozen_dataclass
125
+ @dataclass(frozen=True, slots=True)
132
126
  class GpgBaseError(Exception):
133
127
  status: str
134
128
 
@@ -142,35 +136,35 @@ class GpgBaseError(Exception):
142
136
  super(GpgBaseError, self).__setattr__(field_name, field_type(getattr(self, field_name)))
143
137
 
144
138
 
145
- @frozen_dataclass
139
+ @dataclass(frozen=True, slots=True)
146
140
  class GpgExpSig(GpgBaseError):
147
141
  """The signature with the keyid is good, but the signature is expired."""
148
142
  keyid: str
149
143
  username: str
150
144
 
151
145
 
152
- @frozen_dataclass
146
+ @dataclass(frozen=True, slots=True)
153
147
  class GpgExpKeySig(GpgBaseError):
154
148
  """The signature with the keyid is good, but the signature was made by an expired key."""
155
149
  keyid: str
156
150
  username: str
157
151
 
158
152
 
159
- @frozen_dataclass
153
+ @dataclass(frozen=True, slots=True)
160
154
  class GpgRevKeySig(GpgBaseError):
161
155
  """The signature with the keyid is good, but the signature was made by a revoked key."""
162
156
  keyid: str
163
157
  username: str
164
158
 
165
159
 
166
- @frozen_dataclass
160
+ @dataclass(frozen=True, slots=True)
167
161
  class GpgBadSig(GpgBaseError):
168
162
  """The signature with the keyid has not been verified okay."""
169
163
  keyid: str
170
164
  username: str
171
165
 
172
166
 
173
- @frozen_dataclass
167
+ @dataclass(frozen=True, slots=True)
174
168
  class GpgErrSig(GpgBaseError):
175
169
  """"It was not possible to check the signature. This may be caused by
176
170
  a missing public key or an unsupported algorithm. A RC of 4
@@ -186,24 +180,24 @@ class GpgErrSig(GpgBaseError):
186
180
  fpr: str
187
181
 
188
182
 
189
- @frozen_dataclass
183
+ @dataclass(frozen=True, slots=True)
190
184
  class GpgNoPubkey(GpgBaseError):
191
185
  """The public key is not available."""
192
186
  keyid: str
193
187
 
194
188
 
195
- @frozen_dataclass
189
+ @dataclass(frozen=True, slots=True)
196
190
  class GpgMissingPassPhrase(GpgBaseError):
197
191
  """No passphrase was supplied."""
198
192
 
199
193
 
200
- @frozen_dataclass
194
+ @dataclass(frozen=True, slots=True)
201
195
  class GpgBadPassphrase(GpgBaseError):
202
196
  """The supplied passphrase was wrong or not given."""
203
197
  keyid: str
204
198
 
205
199
 
206
- @frozen_dataclass
200
+ @dataclass(frozen=True, slots=True)
207
201
  class GpgNoData(GpgBaseError):
208
202
  """No data has been found. Codes for WHAT are:
209
203
  - 1 :: No armored data.
@@ -215,7 +209,7 @@ class GpgNoData(GpgBaseError):
215
209
  what: str
216
210
 
217
211
 
218
- @frozen_dataclass
212
+ @dataclass(frozen=True, slots=True)
219
213
  class GpgUnexpected(GpgBaseError):
220
214
  """No data has been found. Codes for WHAT are:
221
215
  - 1 :: No armored data.
@@ -227,7 +221,7 @@ class GpgUnexpected(GpgBaseError):
227
221
  what: str
228
222
 
229
223
 
230
- @frozen_dataclass
224
+ @dataclass(frozen=True, slots=True)
231
225
  class GpgError(GpgBaseError):
232
226
  """This is a generic error status message, it might be followed by error location specific data."""
233
227
  location: str
@@ -235,30 +229,30 @@ class GpgError(GpgBaseError):
235
229
  more: str = ""
236
230
 
237
231
 
238
- @frozen_dataclass
232
+ @dataclass(frozen=True, slots=True)
239
233
  class GpgFailure(GpgBaseError):
240
234
  """This is the counterpart to SUCCESS and used to indicate a program failure."""
241
235
  location: str
242
236
  code: int
243
237
 
244
238
 
245
- @frozen_dataclass
239
+ @dataclass(frozen=True, slots=True)
246
240
  class GpgBadArmor(GpgBaseError):
247
241
  """The ASCII armor is corrupted."""
248
242
 
249
243
 
250
- @frozen_dataclass
244
+ @dataclass(frozen=True, slots=True)
251
245
  class GpgKeyExpired(GpgBaseError):
252
246
  """The key has expired."""
253
247
  timestamp: int
254
248
 
255
249
 
256
- @frozen_dataclass
250
+ @dataclass(frozen=True, slots=True)
257
251
  class GpgKeyRevoked(GpgBaseError):
258
252
  """The used key has been revoked by its owner."""
259
253
 
260
254
 
261
- @frozen_dataclass
255
+ @dataclass(frozen=True, slots=True)
262
256
  class GpgNoSecKey(GpgBaseError):
263
257
  """The secret key is not available."""
264
258
  keyid: str
@@ -0,0 +1,7 @@
1
+ All templates, files and files generated from them in the subdirectories of this one
2
+ are subject to the MIT license when applicable.
3
+
4
+ MIT License:
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,3 +1,4 @@
1
+ #SPDX-License-Identifier: MIT-0
1
2
  FROM ansibleplaybookbundle/apb-base
2
3
 
3
4
  LABEL "com.redhat.apb.spec"=\
@@ -1,3 +1,4 @@
1
+ #SPDX-License-Identifier: MIT-0
1
2
  DOCKERHOST = DOCKERHOST
2
3
  DOCKERORG = DOCKERORG
3
4
  IMAGENAME = {{ role_name }}
@@ -6,17 +6,21 @@ A brief description of the APB goes here.
6
6
  Requirements
7
7
  ------------
8
8
 
9
- Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required.
9
+ Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here.
10
+ For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required.
10
11
 
11
12
  APB Variables
12
13
  --------------
13
14
 
14
- A description of the settable variables for this APB should go here, including any variables that are in defaults/main.yml, vars/main.yml, apb.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (i.e. hostvars, group vars, etc.) should be mentioned here as well.
15
+ A description of the settable variables for this APB should go here, including any variables that are in defaults/main.yml, vars/main.yml, apb.yml, and
16
+ any variables that can/should be set via parameters to the role.
17
+ Any variables that are read from other roles and/or the global scope (i.e. hostvars, group vars, etc.) should be mentioned here as well.
15
18
 
16
19
  Dependencies
17
20
  ------------
18
21
 
19
- A list of other APBs/roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles.
22
+ A list of other APBs/roles hosted on Galaxy should go here, plus any details in regards to
23
+ parameters that may need to be set for other roles, or variables that are used from other roles.
20
24
 
21
25
  Example Playbook
22
26
  ----------------
@@ -1,3 +1,4 @@
1
+ #SPDX-License-Identifier: MIT-0
1
2
  version: '1.0.0'
2
3
  name: {{ role_name }}
3
4
  description: {{ description }}
@@ -1,2 +1,3 @@
1
+ #SPDX-License-Identifier: MIT-0
1
2
  ---
2
3
  # defaults file for {{ role_name }}
@@ -1,2 +1,3 @@
1
+ #SPDX-License-Identifier: MIT-0
1
2
  ---
2
3
  # handlers file for {{ role_name }}
@@ -1,3 +1,4 @@
1
+ #SPDX-License-Identifier: MIT-0
1
2
  galaxy_info:
2
3
  author: {{ author }}
3
4
  description: {{ description }}
@@ -1,3 +1,4 @@
1
+ #SPDX-License-Identifier: MIT-0
1
2
  - name: "{{ role_name }} playbook to deprovision the application"
2
3
  hosts: localhost
3
4
  gather_facts: false
@@ -1,3 +1,4 @@
1
+ #SPDX-License-Identifier: MIT-0
1
2
  - name: "{{ role_name }} playbook to provision the application"
2
3
  hosts: localhost
3
4
  gather_facts: false
@@ -1,2 +1,3 @@
1
+ #SPDX-License-Identifier: MIT-0
1
2
  ---
2
3
  # tasks file for {{ role_name }}
@@ -1,2 +1,3 @@
1
+ #SPDX-License-Identifier: MIT-0
1
2
  [defaults]
2
3
  inventory=./inventory
@@ -1,3 +1,4 @@
1
+ #SPDX-License-Identifier: MIT-0
1
2
  localhost
2
3
 
3
4