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.
- ansible/__main__.py +2 -17
- ansible/cli/__init__.py +3 -15
- ansible/cli/config.py +187 -24
- ansible/cli/console.py +1 -1
- ansible/cli/doc.py +38 -16
- ansible/cli/galaxy.py +3 -49
- ansible/cli/inventory.py +2 -2
- ansible/cli/pull.py +2 -2
- ansible/cli/scripts/ansible_connection_cli_stub.py +1 -10
- ansible/config/base.yml +127 -57
- ansible/config/manager.py +89 -11
- ansible/constants.py +32 -9
- ansible/errors/__init__.py +5 -0
- ansible/executor/interpreter_discovery.py +1 -1
- ansible/executor/play_iterator.py +16 -0
- ansible/executor/playbook_executor.py +1 -4
- ansible/executor/powershell/become_wrapper.ps1 +4 -5
- ansible/executor/powershell/bootstrap_wrapper.ps1 +2 -3
- ansible/executor/powershell/exec_wrapper.ps1 +1 -1
- ansible/executor/powershell/module_manifest.py +2 -2
- ansible/executor/task_executor.py +50 -39
- ansible/executor/task_queue_manager.py +1 -1
- ansible/executor/task_result.py +1 -1
- ansible/galaxy/api.py +3 -4
- ansible/galaxy/collection/__init__.py +21 -10
- ansible/galaxy/collection/concrete_artifact_manager.py +2 -2
- ansible/galaxy/collection/galaxy_api_proxy.py +10 -16
- ansible/galaxy/collection/gpg.py +17 -23
- ansible/galaxy/data/COPYING +7 -0
- ansible/galaxy/data/apb/Dockerfile.j2 +1 -0
- ansible/galaxy/data/apb/Makefile.j2 +1 -0
- ansible/galaxy/data/apb/README.md +7 -3
- ansible/galaxy/data/apb/apb.yml.j2 +1 -0
- ansible/galaxy/data/apb/defaults/main.yml.j2 +1 -0
- ansible/galaxy/data/apb/handlers/main.yml.j2 +1 -0
- ansible/galaxy/data/apb/meta/main.yml.j2 +1 -0
- ansible/galaxy/data/apb/playbooks/deprovision.yml.j2 +1 -0
- ansible/galaxy/data/apb/playbooks/provision.yml.j2 +1 -0
- ansible/galaxy/data/apb/tasks/main.yml.j2 +1 -0
- ansible/galaxy/data/apb/tests/ansible.cfg +1 -0
- ansible/galaxy/data/apb/tests/inventory +1 -0
- ansible/galaxy/data/apb/tests/test.yml.j2 +1 -0
- ansible/galaxy/data/apb/vars/main.yml.j2 +1 -0
- ansible/galaxy/data/collections_galaxy_meta.yml +1 -0
- ansible/galaxy/data/container/defaults/main.yml.j2 +1 -0
- ansible/galaxy/data/container/handlers/main.yml.j2 +1 -0
- ansible/galaxy/data/container/meta/container.yml.j2 +1 -0
- ansible/galaxy/data/container/meta/main.yml.j2 +1 -0
- ansible/galaxy/data/container/tasks/main.yml.j2 +1 -0
- ansible/galaxy/data/container/tests/ansible.cfg +1 -0
- ansible/galaxy/data/container/tests/inventory +1 -0
- ansible/galaxy/data/container/tests/test.yml.j2 +1 -0
- ansible/galaxy/data/container/vars/main.yml.j2 +1 -0
- ansible/galaxy/data/default/collection/README.md.j2 +1 -0
- ansible/galaxy/data/default/collection/galaxy.yml.j2 +1 -0
- ansible/galaxy/data/default/collection/meta/runtime.yml +1 -0
- ansible/galaxy/data/default/collection/plugins/README.md.j2 +1 -0
- ansible/galaxy/data/default/role/defaults/main.yml.j2 +1 -0
- ansible/galaxy/data/default/role/handlers/main.yml.j2 +1 -0
- ansible/galaxy/data/default/role/meta/main.yml.j2 +1 -0
- ansible/galaxy/data/default/role/tasks/main.yml.j2 +1 -0
- ansible/galaxy/data/default/role/tests/inventory +1 -0
- ansible/galaxy/data/default/role/tests/test.yml.j2 +1 -0
- ansible/galaxy/data/default/role/vars/main.yml.j2 +1 -0
- ansible/galaxy/data/network/cliconf_plugins/example.py.j2 +1 -0
- ansible/galaxy/data/network/defaults/main.yml.j2 +1 -0
- ansible/galaxy/data/network/library/example_command.py.j2 +1 -0
- ansible/galaxy/data/network/library/example_config.py.j2 +1 -0
- ansible/galaxy/data/network/library/example_facts.py.j2 +1 -0
- ansible/galaxy/data/network/meta/main.yml.j2 +1 -0
- ansible/galaxy/data/network/module_utils/example.py.j2 +1 -0
- ansible/galaxy/data/network/netconf_plugins/example.py.j2 +1 -0
- ansible/galaxy/data/network/tasks/main.yml.j2 +1 -0
- ansible/galaxy/data/network/terminal_plugins/example.py.j2 +1 -0
- ansible/galaxy/data/network/tests/inventory +1 -0
- ansible/galaxy/data/network/tests/test.yml.j2 +1 -0
- ansible/galaxy/data/network/vars/main.yml.j2 +1 -0
- ansible/galaxy/dependency_resolution/providers.py +3 -3
- ansible/galaxy/role.py +1 -1
- ansible/galaxy/token.py +20 -8
- ansible/keyword_desc.yml +1 -1
- ansible/module_utils/_internal/__init__.py +0 -0
- ansible/module_utils/_internal/_concurrent/__init__.py +0 -0
- ansible/module_utils/_internal/_concurrent/_daemon_threading.py +28 -0
- ansible/module_utils/_internal/_concurrent/_futures.py +21 -0
- ansible/module_utils/ansible_release.py +2 -2
- ansible/module_utils/api.py +2 -2
- ansible/module_utils/basic.py +8 -8
- ansible/module_utils/common/collections.py +1 -1
- ansible/module_utils/common/file.py +0 -6
- ansible/module_utils/common/process.py +22 -9
- ansible/module_utils/common/text/converters.py +5 -8
- ansible/module_utils/common/text/formatters.py +20 -4
- ansible/module_utils/common/validation.py +33 -25
- ansible/module_utils/compat/paramiko.py +6 -1
- ansible/module_utils/compat/selinux.py +2 -2
- ansible/module_utils/connection.py +8 -24
- ansible/module_utils/csharp/Ansible.Become.cs +14 -25
- ansible/module_utils/csharp/Ansible.Process.cs +1 -1
- ansible/module_utils/distro/__init__.py +1 -1
- ansible/module_utils/distro/_distro.py +8 -4
- ansible/module_utils/facts/collector.py +2 -0
- ansible/module_utils/facts/default_collectors.py +3 -1
- ansible/module_utils/facts/hardware/aix.py +54 -52
- ansible/module_utils/facts/hardware/darwin.py +37 -34
- ansible/module_utils/facts/hardware/freebsd.py +55 -15
- ansible/module_utils/facts/hardware/hpux.py +3 -0
- ansible/module_utils/facts/hardware/linux.py +101 -57
- ansible/module_utils/facts/hardware/netbsd.py +3 -0
- ansible/module_utils/facts/hardware/openbsd.py +4 -1
- ansible/module_utils/facts/hardware/sunos.py +7 -1
- ansible/module_utils/facts/network/aix.py +16 -17
- ansible/module_utils/facts/network/fc_wwn.py +4 -1
- ansible/module_utils/facts/network/hpux.py +21 -4
- ansible/module_utils/facts/network/iscsi.py +7 -8
- ansible/module_utils/facts/network/linux.py +0 -2
- ansible/module_utils/facts/other/facter.py +9 -4
- ansible/module_utils/facts/other/ohai.py +5 -5
- ansible/module_utils/facts/packages.py +49 -7
- ansible/module_utils/facts/sysctl.py +33 -31
- ansible/module_utils/facts/system/distribution.py +1 -1
- ansible/module_utils/facts/system/local.py +12 -22
- ansible/module_utils/facts/system/service_mgr.py +3 -1
- ansible/module_utils/facts/system/systemd.py +47 -0
- ansible/module_utils/powershell/Ansible.ModuleUtils.AddType.psm1 +1 -1
- ansible/module_utils/powershell/Ansible.ModuleUtils.CamelConversion.psm1 +1 -1
- ansible/module_utils/splitter.py +1 -1
- ansible/modules/add_host.py +1 -1
- ansible/modules/apt.py +43 -32
- ansible/modules/apt_key.py +6 -6
- ansible/modules/apt_repository.py +23 -14
- ansible/modules/assemble.py +7 -2
- ansible/modules/assert.py +4 -4
- ansible/modules/blockinfile.py +3 -6
- ansible/modules/command.py +1 -1
- ansible/modules/copy.py +4 -4
- ansible/modules/cron.py +13 -10
- ansible/modules/deb822_repository.py +16 -17
- ansible/modules/debconf.py +9 -9
- ansible/modules/debug.py +1 -1
- ansible/modules/dnf.py +79 -164
- ansible/modules/dnf5.py +54 -29
- ansible/modules/dpkg_selections.py +2 -2
- ansible/modules/expect.py +2 -2
- ansible/modules/fetch.py +2 -2
- ansible/modules/file.py +5 -3
- ansible/modules/find.py +40 -12
- ansible/modules/gather_facts.py +4 -2
- ansible/modules/get_url.py +29 -24
- ansible/modules/git.py +35 -35
- ansible/modules/group.py +71 -1
- ansible/modules/hostname.py +2 -4
- ansible/modules/include_vars.py +5 -5
- ansible/modules/iptables.py +13 -16
- ansible/modules/known_hosts.py +16 -13
- ansible/modules/lineinfile.py +1 -4
- ansible/modules/meta.py +6 -1
- ansible/modules/mount_facts.py +651 -0
- ansible/modules/package_facts.py +63 -80
- ansible/modules/pause.py +4 -3
- ansible/modules/pip.py +14 -14
- ansible/modules/replace.py +1 -4
- ansible/modules/rpm_key.py +31 -11
- ansible/modules/service.py +8 -8
- ansible/modules/service_facts.py +20 -5
- ansible/modules/set_stats.py +1 -1
- ansible/modules/setup.py +3 -3
- ansible/modules/stat.py +3 -3
- ansible/modules/subversion.py +1 -1
- ansible/modules/systemd.py +16 -10
- ansible/modules/systemd_service.py +16 -10
- ansible/modules/sysvinit.py +4 -4
- ansible/modules/unarchive.py +35 -22
- ansible/modules/uri.py +24 -18
- ansible/modules/user.py +145 -12
- ansible/modules/validate_argument_spec.py +3 -3
- ansible/modules/wait_for_connection.py +2 -1
- ansible/modules/yum_repository.py +136 -179
- ansible/parsing/dataloader.py +2 -2
- ansible/parsing/mod_args.py +11 -10
- ansible/parsing/vault/__init__.py +8 -3
- ansible/parsing/yaml/constructor.py +10 -8
- ansible/parsing/yaml/objects.py +1 -1
- ansible/playbook/base.py +12 -23
- ansible/playbook/helpers.py +4 -0
- ansible/playbook/loop_control.py +8 -0
- ansible/playbook/play.py +4 -22
- ansible/playbook/play_context.py +0 -16
- ansible/playbook/playbook_include.py +2 -2
- ansible/playbook/role/__init__.py +2 -2
- ansible/plugins/__init__.py +2 -0
- ansible/plugins/action/__init__.py +7 -9
- ansible/plugins/action/dnf.py +7 -5
- ansible/plugins/action/package.py +5 -4
- ansible/plugins/action/reboot.py +2 -2
- ansible/plugins/become/__init__.py +1 -1
- ansible/plugins/callback/__init__.py +44 -3
- ansible/plugins/callback/default.py +1 -1
- ansible/plugins/cliconf/__init__.py +1 -1
- ansible/plugins/connection/paramiko_ssh.py +2 -80
- ansible/plugins/connection/psrp.py +33 -82
- ansible/plugins/connection/ssh.py +0 -8
- ansible/plugins/connection/winrm.py +46 -1
- ansible/plugins/doc_fragments/connection_pipelining.py +2 -2
- ansible/plugins/doc_fragments/constructed.py +10 -10
- ansible/plugins/doc_fragments/default_callback.py +8 -8
- ansible/plugins/doc_fragments/files.py +5 -5
- ansible/plugins/doc_fragments/inventory_cache.py +2 -2
- ansible/plugins/doc_fragments/result_format_callback.py +6 -6
- ansible/plugins/doc_fragments/return_common.py +1 -1
- ansible/plugins/doc_fragments/shell_common.py +2 -10
- ansible/plugins/doc_fragments/shell_windows.py +0 -9
- ansible/plugins/doc_fragments/url.py +2 -2
- ansible/plugins/doc_fragments/url_windows.py +4 -5
- ansible/plugins/doc_fragments/validate.py +1 -1
- ansible/plugins/filter/core.py +2 -0
- ansible/plugins/filter/human_to_bytes.yml +9 -0
- ansible/plugins/filter/password_hash.yml +1 -1
- ansible/plugins/filter/strftime.yml +1 -1
- ansible/plugins/filter/to_nice_json.yml +7 -3
- ansible/plugins/filter/to_uuid.yml +1 -1
- ansible/plugins/inventory/script.py +1 -1
- ansible/plugins/list.py +1 -1
- ansible/plugins/loader.py +0 -11
- ansible/plugins/lookup/config.py +1 -1
- ansible/plugins/lookup/csvfile.py +21 -9
- ansible/plugins/lookup/env.py +8 -9
- ansible/plugins/lookup/ini.py +10 -1
- ansible/plugins/lookup/random_choice.py +2 -2
- ansible/plugins/lookup/url.py +7 -2
- ansible/plugins/shell/__init__.py +15 -20
- ansible/plugins/shell/powershell.py +9 -6
- ansible/plugins/strategy/__init__.py +16 -7
- ansible/plugins/test/core.py +23 -1
- ansible/plugins/test/issubset.yml +1 -1
- ansible/plugins/test/subset.yml +1 -1
- ansible/plugins/test/timedout.yml +20 -0
- ansible/plugins/test/vault_encrypted.yml +6 -6
- ansible/plugins/test/vaulted_file.yml +19 -0
- ansible/release.py +2 -2
- ansible/template/__init__.py +3 -8
- ansible/utils/collection_loader/_collection_finder.py +23 -55
- ansible/utils/display.py +44 -31
- ansible/utils/jsonrpc.py +1 -1
- ansible/utils/listify.py +1 -5
- ansible/utils/path.py +3 -0
- ansible/utils/vars.py +18 -27
- ansible/vars/manager.py +7 -150
- ansible/vars/plugins.py +1 -1
- ansible_core-2.18.0.dist-info/Apache-License.txt +202 -0
- {ansible_core-2.17.6.dist-info → ansible_core-2.18.0.dist-info}/METADATA +36 -23
- ansible_core-2.18.0.dist-info/MIT-license.txt +14 -0
- ansible_core-2.18.0.dist-info/PSF-license.txt +48 -0
- {ansible_core-2.17.6.dist-info → ansible_core-2.18.0.dist-info}/RECORD +316 -311
- {ansible_core-2.17.6.dist-info → ansible_core-2.18.0.dist-info}/entry_points.txt +1 -1
- ansible_core-2.18.0.dist-info/simplified_bsd.txt +8 -0
- ansible_test/_data/completion/docker.txt +7 -7
- ansible_test/_data/completion/remote.txt +5 -4
- ansible_test/_data/completion/windows.txt +4 -4
- ansible_test/_data/requirements/ansible-test.txt +1 -2
- ansible_test/_data/requirements/constraints.txt +1 -2
- ansible_test/_data/requirements/sanity.ansible-doc.txt +3 -3
- ansible_test/_data/requirements/sanity.changelog.in +1 -1
- ansible_test/_data/requirements/sanity.changelog.txt +4 -4
- ansible_test/_data/requirements/sanity.import.plugin.txt +2 -2
- ansible_test/_data/requirements/sanity.import.txt +1 -1
- ansible_test/_data/requirements/sanity.integration-aliases.txt +1 -1
- ansible_test/_data/requirements/sanity.pep8.txt +1 -1
- ansible_test/_data/requirements/sanity.pylint.txt +6 -8
- ansible_test/_data/requirements/sanity.runtime-metadata.txt +2 -2
- ansible_test/_data/requirements/sanity.validate-modules.txt +3 -3
- ansible_test/_data/requirements/sanity.yamllint.in +1 -0
- ansible_test/_data/requirements/sanity.yamllint.txt +1 -1
- ansible_test/_internal/ansible_util.py +8 -35
- ansible_test/_internal/ci/azp.py +1 -1
- ansible_test/_internal/classification/__init__.py +0 -2
- ansible_test/_internal/cli/parsers/key_value_parsers.py +3 -0
- ansible_test/_internal/commands/integration/cloud/hcloud.py +1 -1
- ansible_test/_internal/commands/integration/cloud/httptester.py +1 -1
- ansible_test/_internal/commands/integration/cloud/nios.py +1 -1
- ansible_test/_internal/commands/sanity/__init__.py +96 -19
- ansible_test/_internal/commands/sanity/pylint.py +20 -24
- ansible_test/_internal/completion.py +2 -0
- ansible_test/_internal/constants.py +0 -1
- ansible_test/_internal/coverage_util.py +1 -2
- ansible_test/_internal/docker_util.py +1 -1
- ansible_test/_internal/encoding.py +4 -4
- ansible_test/_internal/host_configs.py +10 -0
- ansible_test/_internal/host_profiles.py +9 -13
- ansible_test/_internal/pypi_proxy.py +1 -1
- ansible_test/_internal/python_requirements.py +5 -14
- ansible_test/_internal/timeout.py +1 -1
- ansible_test/_internal/util.py +40 -0
- ansible_test/_internal/util_common.py +5 -1
- ansible_test/_util/controller/sanity/code-smell/action-plugin-docs.json +3 -1
- ansible_test/_util/controller/sanity/code-smell/action-plugin-docs.py +6 -3
- ansible_test/_util/controller/sanity/code-smell/empty-init.json +0 -2
- ansible_test/_util/controller/sanity/pylint/config/ansible-test-target.cfg +5 -0
- ansible_test/_util/controller/sanity/pylint/config/ansible-test.cfg +5 -0
- ansible_test/_util/controller/sanity/pylint/config/code-smell.cfg +5 -0
- ansible_test/_util/controller/sanity/pylint/config/collection.cfg +6 -0
- ansible_test/_util/controller/sanity/pylint/config/default.cfg +6 -0
- ansible_test/_util/controller/sanity/pylint/plugins/deprecated.py +1 -19
- ansible_test/_util/controller/sanity/shellcheck/exclude.txt +1 -0
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py +67 -2
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/schema.py +27 -5
- ansible_test/_util/target/cli/ansible_test_cli_stub.py +0 -0
- ansible_test/_util/target/common/constants.py +2 -2
- ansible_test/_util/target/injector/python.py +5 -0
- ansible_test/_util/target/pytest/plugins/ansible_pytest_coverage.py +6 -0
- ansible_test/_util/target/sanity/import/importer.py +1 -1
- ansible_test/_util/target/setup/bootstrap.sh +6 -17
- ansible_test/_util/target/setup/requirements.py +18 -24
- ansible_test/config/config.yml +1 -1
- ansible_core-2.17.6.data/scripts/ansible-test +0 -44
- ansible_test/_data/requirements/sanity.mypy.in +0 -10
- ansible_test/_data/requirements/sanity.mypy.txt +0 -18
- ansible_test/_internal/commands/sanity/mypy.py +0 -274
- ansible_test/_util/controller/sanity/mypy/ansible-core.ini +0 -116
- ansible_test/_util/controller/sanity/mypy/ansible-test.ini +0 -27
- ansible_test/_util/controller/sanity/mypy/modules.ini +0 -92
- ansible_test/_util/controller/sanity/mypy/packaging.ini +0 -20
- {ansible_core-2.17.6.dist-info → ansible_core-2.18.0.dist-info}/COPYING +0 -0
- {ansible_core-2.17.6.dist-info → ansible_core-2.18.0.dist-info}/WHEEL +0 -0
- {ansible_core-2.17.6.dist-info → ansible_core-2.18.0.dist-info}/top_level.txt +0 -0
|
@@ -126,7 +126,7 @@ class CollectionDependencyProviderBase(AbstractProvider):
|
|
|
126
126
|
the current candidate list
|
|
127
127
|
|
|
128
128
|
* ``parent`` specifies the candidate that provides
|
|
129
|
-
(
|
|
129
|
+
(depended on) the requirement, or `None`
|
|
130
130
|
to indicate a root requirement.
|
|
131
131
|
|
|
132
132
|
resolvelib >=0.7.0, < 0.8.0
|
|
@@ -202,7 +202,7 @@ class CollectionDependencyProviderBase(AbstractProvider):
|
|
|
202
202
|
remote archives), the one-and-only match is returned
|
|
203
203
|
|
|
204
204
|
For a "named" requirement, Galaxy-compatible APIs are consulted
|
|
205
|
-
to find concrete candidates for this requirement.
|
|
205
|
+
to find concrete candidates for this requirement. If there's a
|
|
206
206
|
pre-installed candidate, it's prepended in front of others.
|
|
207
207
|
|
|
208
208
|
resolvelib >=0.5.3, <0.6.0
|
|
@@ -437,7 +437,7 @@ class CollectionDependencyProviderBase(AbstractProvider):
|
|
|
437
437
|
# FIXME: differs. So how do we resolve this case? Priority?
|
|
438
438
|
# FIXME: Taking into account a pinned hash? Exploding on
|
|
439
439
|
# FIXME: any differences?
|
|
440
|
-
# NOTE: The underlying
|
|
440
|
+
# NOTE: The underlying implementation currently uses first found
|
|
441
441
|
req_map = self._api_proxy.get_collection_dependencies(candidate)
|
|
442
442
|
|
|
443
443
|
# NOTE: This guard expression MUST perform an early exit only
|
ansible/galaxy/role.py
CHANGED
|
@@ -256,7 +256,7 @@ class GalaxyRole(object):
|
|
|
256
256
|
display.display("- downloading role from %s" % archive_url)
|
|
257
257
|
|
|
258
258
|
try:
|
|
259
|
-
url_file = open_url(archive_url, validate_certs=self._validate_certs, http_agent=user_agent())
|
|
259
|
+
url_file = open_url(archive_url, validate_certs=self._validate_certs, http_agent=user_agent(), timeout=60)
|
|
260
260
|
temp_file = tempfile.NamedTemporaryFile(delete=False)
|
|
261
261
|
data = url_file.read()
|
|
262
262
|
while data:
|
ansible/galaxy/token.py
CHANGED
|
@@ -21,11 +21,14 @@
|
|
|
21
21
|
from __future__ import annotations
|
|
22
22
|
|
|
23
23
|
import base64
|
|
24
|
-
import os
|
|
25
24
|
import json
|
|
25
|
+
import os
|
|
26
|
+
import time
|
|
26
27
|
from stat import S_IRUSR, S_IWUSR
|
|
28
|
+
from urllib.error import HTTPError
|
|
27
29
|
|
|
28
30
|
from ansible import constants as C
|
|
31
|
+
from ansible.galaxy.api import GalaxyError
|
|
29
32
|
from ansible.galaxy.user_agent import user_agent
|
|
30
33
|
from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text
|
|
31
34
|
from ansible.module_utils.common.yaml import yaml_dump, yaml_load
|
|
@@ -57,12 +60,16 @@ class KeycloakToken(object):
|
|
|
57
60
|
self.client_id = client_id
|
|
58
61
|
if self.client_id is None:
|
|
59
62
|
self.client_id = 'cloud-services'
|
|
63
|
+
self._expiration = None
|
|
60
64
|
|
|
61
65
|
def _form_payload(self):
|
|
62
66
|
return 'grant_type=refresh_token&client_id=%s&refresh_token=%s' % (self.client_id,
|
|
63
67
|
self.access_token)
|
|
64
68
|
|
|
65
69
|
def get(self):
|
|
70
|
+
if self._expiration and time.time() >= self._expiration:
|
|
71
|
+
self._token = None
|
|
72
|
+
|
|
66
73
|
if self._token:
|
|
67
74
|
return self._token
|
|
68
75
|
|
|
@@ -76,15 +83,20 @@ class KeycloakToken(object):
|
|
|
76
83
|
# or 'azp' (Authorized party - the party to which the ID Token was issued)
|
|
77
84
|
payload = self._form_payload()
|
|
78
85
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
86
|
+
try:
|
|
87
|
+
resp = open_url(to_native(self.auth_url),
|
|
88
|
+
data=payload,
|
|
89
|
+
validate_certs=self.validate_certs,
|
|
90
|
+
method='POST',
|
|
91
|
+
http_agent=user_agent())
|
|
92
|
+
except HTTPError as e:
|
|
93
|
+
raise GalaxyError(e, 'Unable to get access token')
|
|
84
94
|
|
|
85
|
-
|
|
95
|
+
data = json.load(resp)
|
|
86
96
|
|
|
87
|
-
|
|
97
|
+
# So that we have a buffer, expire the token in ~2/3 the given value
|
|
98
|
+
expires_in = data['expires_in'] // 3 * 2
|
|
99
|
+
self._expiration = time.time() + expires_in
|
|
88
100
|
|
|
89
101
|
# - extract 'access_token'
|
|
90
102
|
self._token = data.get('access_token')
|
ansible/keyword_desc.yml
CHANGED
|
@@ -61,7 +61,7 @@ serial: Explicitly define how Ansible batches the execution of the current play
|
|
|
61
61
|
strategy: Allows you to choose the strategy plugin to use for the play. See :ref:`strategy_plugins`.
|
|
62
62
|
tags: Tags applied to the task or included tasks, this allows selecting subsets of tasks from the command line.
|
|
63
63
|
tasks: Main list of tasks to execute in the play, they run after :term:`roles` and before :term:`post_tasks`.
|
|
64
|
-
timeout: Time limit for the task to execute in, if exceeded Ansible will interrupt
|
|
64
|
+
timeout: Time limit for the task action to execute in, if exceeded, Ansible will interrupt the process. Timeout does not include templating or looping.
|
|
65
65
|
throttle: Limit the number of concurrent task runs on task, block and playbook level. This is independent of the forks and serial settings, but cannot be set higher than those limits. For example, if forks is set to 10 and the throttle is set to 15, at most 10 hosts will be operated on in parallel.
|
|
66
66
|
until: "This keyword implies a ':term:`retries` loop' that will go on until the condition supplied here is met or we hit the :term:`retries` limit."
|
|
67
67
|
vars: Dictionary/map of variables
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""Proxy stdlib threading module that only supports non-joinable daemon threads."""
|
|
2
|
+
# NB: all new local module attrs are _ prefixed to ensure an identical public attribute surface area to the module we're proxying
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations as _annotations
|
|
5
|
+
|
|
6
|
+
import threading as _threading
|
|
7
|
+
import typing as _t
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class _DaemonThread(_threading.Thread):
|
|
11
|
+
"""
|
|
12
|
+
Daemon-only Thread subclass; prevents running threads of this type from blocking interpreter shutdown and process exit.
|
|
13
|
+
The join() method is a no-op.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
def __init__(self, *args, daemon: bool | None = None, **kwargs) -> None:
|
|
17
|
+
super().__init__(*args, daemon=daemon or True, **kwargs)
|
|
18
|
+
|
|
19
|
+
def join(self, timeout=None) -> None:
|
|
20
|
+
"""ThreadPoolExecutor's atexit handler joins all queue threads before allowing shutdown; prevent them from blocking."""
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
Thread = _DaemonThread # shadow the real Thread attr with our _DaemonThread
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def __getattr__(name: str) -> _t.Any:
|
|
27
|
+
"""Delegate anything not defined locally to the real `threading` module."""
|
|
28
|
+
return getattr(_threading, name)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""Utilities for concurrent code execution using futures."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import concurrent.futures
|
|
6
|
+
import types
|
|
7
|
+
|
|
8
|
+
from . import _daemon_threading
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class DaemonThreadPoolExecutor(concurrent.futures.ThreadPoolExecutor):
|
|
12
|
+
"""ThreadPoolExecutor subclass that creates non-joinable daemon threads for non-blocking pool and process shutdown with abandoned threads."""
|
|
13
|
+
|
|
14
|
+
atc = concurrent.futures.ThreadPoolExecutor._adjust_thread_count
|
|
15
|
+
|
|
16
|
+
# clone the base class `_adjust_thread_count` method with a copy of its globals dict
|
|
17
|
+
_adjust_thread_count = types.FunctionType(atc.__code__, atc.__globals__.copy(), name=atc.__name__, argdefs=atc.__defaults__, closure=atc.__closure__)
|
|
18
|
+
# patch the method closure's `threading` module import to use our daemon-only thread factory instead
|
|
19
|
+
_adjust_thread_count.__globals__.update(threading=_daemon_threading)
|
|
20
|
+
|
|
21
|
+
del atc # don't expose this as a class attribute
|
ansible/module_utils/api.py
CHANGED
|
@@ -28,7 +28,7 @@ from __future__ import annotations
|
|
|
28
28
|
import copy
|
|
29
29
|
import functools
|
|
30
30
|
import itertools
|
|
31
|
-
import
|
|
31
|
+
import secrets
|
|
32
32
|
import sys
|
|
33
33
|
import time
|
|
34
34
|
|
|
@@ -131,7 +131,7 @@ def generate_jittered_backoff(retries=10, delay_base=3, delay_threshold=60):
|
|
|
131
131
|
:param delay_threshold: The maximum time in seconds for any delay.
|
|
132
132
|
"""
|
|
133
133
|
for retry in range(0, retries):
|
|
134
|
-
yield
|
|
134
|
+
yield secrets.randbelow(min(delay_threshold, delay_base * 2 ** retry))
|
|
135
135
|
|
|
136
136
|
|
|
137
137
|
def retry_never(exception_or_result):
|
ansible/module_utils/basic.py
CHANGED
|
@@ -9,7 +9,7 @@ import sys
|
|
|
9
9
|
|
|
10
10
|
# Used for determining if the system is running a new enough python version
|
|
11
11
|
# and should only restrict on our documented minimum versions
|
|
12
|
-
_PY_MIN = (3,
|
|
12
|
+
_PY_MIN = (3, 8)
|
|
13
13
|
|
|
14
14
|
if sys.version_info < _PY_MIN:
|
|
15
15
|
print(json.dumps(dict(
|
|
@@ -458,7 +458,7 @@ class AnsibleModule(object):
|
|
|
458
458
|
self._selinux_mls_enabled = None
|
|
459
459
|
self._selinux_initial_context = None
|
|
460
460
|
|
|
461
|
-
# finally, make sure we're in a
|
|
461
|
+
# finally, make sure we're in a logical working dir
|
|
462
462
|
self._set_cwd()
|
|
463
463
|
|
|
464
464
|
@property
|
|
@@ -1202,6 +1202,7 @@ class AnsibleModule(object):
|
|
|
1202
1202
|
setattr(self, PASS_VARS[k][0], PASS_VARS[k][1])
|
|
1203
1203
|
|
|
1204
1204
|
def safe_eval(self, value, locals=None, include_exceptions=False):
|
|
1205
|
+
# deprecated: description='no longer used in the codebase' core_version='2.21'
|
|
1205
1206
|
return safe_eval(value, locals, include_exceptions)
|
|
1206
1207
|
|
|
1207
1208
|
def _load_params(self):
|
|
@@ -1353,9 +1354,10 @@ class AnsibleModule(object):
|
|
|
1353
1354
|
Find system executable in PATH.
|
|
1354
1355
|
|
|
1355
1356
|
:param arg: The executable to find.
|
|
1356
|
-
:param required: if executable is not found and required is ``True``, fail_json
|
|
1357
|
+
:param required: if the executable is not found and required is ``True``, fail_json
|
|
1357
1358
|
:param opt_dirs: optional list of directories to search in addition to ``PATH``
|
|
1358
|
-
:returns: if found return full path; otherwise return None
|
|
1359
|
+
:returns: if found return full path; otherwise return original arg, unless 'warning' then return None
|
|
1360
|
+
:raises: Sysexit: if arg is not found and required=True (via fail_json)
|
|
1359
1361
|
'''
|
|
1360
1362
|
|
|
1361
1363
|
bin_path = None
|
|
@@ -1364,8 +1366,6 @@ class AnsibleModule(object):
|
|
|
1364
1366
|
except ValueError as e:
|
|
1365
1367
|
if required:
|
|
1366
1368
|
self.fail_json(msg=to_text(e))
|
|
1367
|
-
else:
|
|
1368
|
-
return bin_path
|
|
1369
1369
|
|
|
1370
1370
|
return bin_path
|
|
1371
1371
|
|
|
@@ -1432,7 +1432,7 @@ class AnsibleModule(object):
|
|
|
1432
1432
|
kwargs['deprecations'] = deprecations
|
|
1433
1433
|
|
|
1434
1434
|
# preserve bools/none from no_log
|
|
1435
|
-
# TODO: once python version on target high enough, dict
|
|
1435
|
+
# TODO: once python version on target high enough, dict comprehensions
|
|
1436
1436
|
preserved = {}
|
|
1437
1437
|
for k, v in kwargs.items():
|
|
1438
1438
|
if v is None or isinstance(v, bool):
|
|
@@ -2061,7 +2061,7 @@ class AnsibleModule(object):
|
|
|
2061
2061
|
# not as exact as above, but should be good enough for most platforms that fail the previous call
|
|
2062
2062
|
buffer_size = select.PIPE_BUF
|
|
2063
2063
|
except Exception:
|
|
2064
|
-
buffer_size = 9000 # use
|
|
2064
|
+
buffer_size = 9000 # use logical default JIC
|
|
2065
2065
|
|
|
2066
2066
|
return buffer_size
|
|
2067
2067
|
|
|
@@ -65,7 +65,7 @@ class ImmutableDict(Hashable, Mapping):
|
|
|
65
65
|
|
|
66
66
|
|
|
67
67
|
def is_string(seq):
|
|
68
|
-
"""Identify whether the input has a string-like type (
|
|
68
|
+
"""Identify whether the input has a string-like type (including bytes)."""
|
|
69
69
|
# AnsibleVaultEncryptedUnicode inherits from Sequence, but is expected to be a string like object
|
|
70
70
|
return isinstance(seq, (text_type, binary_type)) or getattr(seq, '__ENCRYPTED__', False)
|
|
71
71
|
|
|
@@ -12,13 +12,18 @@ from ansible.module_utils.common.warnings import deprecate
|
|
|
12
12
|
def get_bin_path(arg, opt_dirs=None, required=None):
|
|
13
13
|
'''
|
|
14
14
|
Find system executable in PATH. Raises ValueError if the executable is not found.
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
|
|
16
|
+
:param arg: the executable to find
|
|
17
|
+
:type arg: string
|
|
18
|
+
:param opt_dirs: optional list of directories to search in addition to PATH
|
|
19
|
+
:type opt_dirs: list of strings
|
|
20
|
+
:param required: DEPRECATED. This parameter will be removed in 2.21
|
|
21
|
+
:type required: boolean
|
|
22
|
+
:returns: path to arg (should be abs path unless PATH or opt_dirs are relative paths)
|
|
23
|
+
:raises: ValueError: if arg is not found
|
|
24
|
+
|
|
19
25
|
In addition to PATH and opt_dirs, this function also looks through /sbin, /usr/sbin and /usr/local/sbin. A lot of
|
|
20
26
|
modules, especially for gathering facts, depend on this behaviour.
|
|
21
|
-
If found return full path, otherwise raise ValueError.
|
|
22
27
|
'''
|
|
23
28
|
if required is not None:
|
|
24
29
|
deprecate(
|
|
@@ -27,26 +32,34 @@ def get_bin_path(arg, opt_dirs=None, required=None):
|
|
|
27
32
|
collection_name="ansible.builtin",
|
|
28
33
|
)
|
|
29
34
|
|
|
35
|
+
paths = []
|
|
36
|
+
sbin_paths = ['/sbin', '/usr/sbin', '/usr/local/sbin']
|
|
30
37
|
opt_dirs = [] if opt_dirs is None else opt_dirs
|
|
31
38
|
|
|
32
|
-
|
|
33
|
-
|
|
39
|
+
# Construct possible paths with precedence
|
|
40
|
+
# passed in paths
|
|
34
41
|
for d in opt_dirs:
|
|
35
42
|
if d is not None and os.path.exists(d):
|
|
36
43
|
paths.append(d)
|
|
44
|
+
# system configured paths
|
|
37
45
|
paths += os.environ.get('PATH', '').split(os.pathsep)
|
|
38
|
-
|
|
39
|
-
#
|
|
46
|
+
|
|
47
|
+
# existing /sbin dirs, if not there already
|
|
40
48
|
for p in sbin_paths:
|
|
41
49
|
if p not in paths and os.path.exists(p):
|
|
42
50
|
paths.append(p)
|
|
51
|
+
|
|
52
|
+
# Search for binary
|
|
53
|
+
bin_path = None
|
|
43
54
|
for d in paths:
|
|
44
55
|
if not d:
|
|
45
56
|
continue
|
|
46
57
|
path = os.path.join(d, arg)
|
|
47
58
|
if os.path.exists(path) and not os.path.isdir(path) and is_executable(path):
|
|
59
|
+
# fist found wins
|
|
48
60
|
bin_path = path
|
|
49
61
|
break
|
|
62
|
+
|
|
50
63
|
if bin_path is None:
|
|
51
64
|
raise ValueError('Failed to find required executable "%s" in paths: %s' % (arg, os.pathsep.join(paths)))
|
|
52
65
|
|
|
@@ -267,14 +267,11 @@ def _json_encode_fallback(obj):
|
|
|
267
267
|
|
|
268
268
|
|
|
269
269
|
def jsonify(data, **kwargs):
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
continue
|
|
276
|
-
return json.dumps(new_data, default=_json_encode_fallback, **kwargs)
|
|
277
|
-
raise UnicodeError('Invalid unicode encoding encountered')
|
|
270
|
+
try:
|
|
271
|
+
new_data = container_to_text(data, encoding='utf-8')
|
|
272
|
+
except UnicodeDecodeError:
|
|
273
|
+
raise UnicodeError('Invalid unicode encoding encountered')
|
|
274
|
+
return json.dumps(new_data, default=_json_encode_fallback, **kwargs)
|
|
278
275
|
|
|
279
276
|
|
|
280
277
|
def container_to_bytes(d, encoding='utf-8', errors='surrogate_or_strict'):
|
|
@@ -20,6 +20,18 @@ SIZE_RANGES = {
|
|
|
20
20
|
'B': 1,
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
VALID_UNITS = {
|
|
24
|
+
'B': (('byte', 'B'), ('bit', 'b')),
|
|
25
|
+
'K': (('kilobyte', 'KB'), ('kilobit', 'Kb')),
|
|
26
|
+
'M': (('megabyte', 'MB'), ('megabit', 'Mb')),
|
|
27
|
+
'G': (('gigabyte', 'GB'), ('gigabit', 'Gb')),
|
|
28
|
+
'T': (('terabyte', 'TB'), ('terabit', 'Tb')),
|
|
29
|
+
'P': (('petabyte', 'PB'), ('petabit', 'Pb')),
|
|
30
|
+
'E': (('exabyte', 'EB'), ('exabit', 'Eb')),
|
|
31
|
+
'Z': (('zetabyte', 'ZB'), ('zetabit', 'Zb')),
|
|
32
|
+
'Y': (('yottabyte', 'YB'), ('yottabit', 'Yb')),
|
|
33
|
+
}
|
|
34
|
+
|
|
23
35
|
|
|
24
36
|
def lenient_lowercase(lst):
|
|
25
37
|
"""Lowercase elements of a list.
|
|
@@ -53,7 +65,8 @@ def human_to_bytes(number, default_unit=None, isbits=False):
|
|
|
53
65
|
The function expects 'b' (lowercase) as a bit identifier, e.g. 'Mb'/'Kb'/etc.
|
|
54
66
|
if 'MB'/'KB'/... is passed, the ValueError will be rased.
|
|
55
67
|
"""
|
|
56
|
-
m = re.search(r'
|
|
68
|
+
m = re.search(r'^([0-9]*\.?[0-9]+)(?:\s*([A-Za-z]+))?\s*$', str(number))
|
|
69
|
+
|
|
57
70
|
if m is None:
|
|
58
71
|
raise ValueError("human_to_bytes() can't interpret following string: %s" % str(number))
|
|
59
72
|
try:
|
|
@@ -86,10 +99,13 @@ def human_to_bytes(number, default_unit=None, isbits=False):
|
|
|
86
99
|
expect_message = 'expect %s%s or %s' % (range_key, unit_class, range_key)
|
|
87
100
|
if range_key == 'B':
|
|
88
101
|
expect_message = 'expect %s or %s' % (unit_class, unit_class_name)
|
|
89
|
-
|
|
90
|
-
if
|
|
102
|
+
unit_group = VALID_UNITS.get(range_key, None)
|
|
103
|
+
if unit_group is None:
|
|
104
|
+
raise ValueError(f"human_to_bytes() can't interpret a valid unit for {range_key}")
|
|
105
|
+
isbits_flag = 1 if isbits else 0
|
|
106
|
+
if unit.lower() == unit_group[isbits_flag][0]:
|
|
91
107
|
pass
|
|
92
|
-
elif unit[1]
|
|
108
|
+
elif unit != unit_group[isbits_flag][1]:
|
|
93
109
|
raise ValueError("human_to_bytes() failed to convert %s. Value is not a valid string (%s)" % (number, expect_message))
|
|
94
110
|
|
|
95
111
|
return int(round(num * limit))
|