ansible-core 2.15.4rc1__py3-none-any.whl → 2.16.0b2__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/cli/__init__.py +3 -3
- ansible/cli/adhoc.py +1 -1
- ansible/cli/arguments/option_helpers.py +15 -5
- ansible/cli/config.py +2 -2
- ansible/cli/console.py +21 -17
- ansible/cli/doc.py +8 -9
- ansible/cli/galaxy.py +60 -27
- ansible/cli/inventory.py +1 -1
- ansible/cli/playbook.py +1 -1
- ansible/cli/pull.py +2 -2
- ansible/cli/scripts/ansible_connection_cli_stub.py +1 -1
- ansible/cli/vault.py +11 -6
- ansible/collections/__init__.py +0 -29
- ansible/collections/list.py +23 -44
- ansible/config/ansible_builtin_runtime.yml +8 -4
- ansible/config/base.yml +34 -22
- ansible/config/manager.py +1 -1
- ansible/constants.py +3 -5
- ansible/errors/__init__.py +1 -1
- ansible/executor/interpreter_discovery.py +1 -1
- ansible/executor/module_common.py +39 -32
- ansible/executor/play_iterator.py +0 -15
- ansible/executor/playbook_executor.py +3 -3
- ansible/executor/powershell/module_manifest.py +1 -1
- ansible/executor/powershell/module_wrapper.ps1 +4 -1
- ansible/executor/process/worker.py +22 -7
- ansible/executor/task_executor.py +39 -40
- ansible/executor/task_queue_manager.py +8 -11
- ansible/galaxy/__init__.py +1 -1
- ansible/galaxy/api.py +8 -11
- ansible/galaxy/collection/__init__.py +17 -4
- ansible/galaxy/collection/concrete_artifact_manager.py +7 -2
- ansible/galaxy/collection/galaxy_api_proxy.py +1 -1
- ansible/galaxy/data/container/README.md +3 -5
- ansible/galaxy/dependency_resolution/__init__.py +1 -6
- ansible/galaxy/dependency_resolution/dataclasses.py +22 -1
- ansible/galaxy/dependency_resolution/providers.py +61 -69
- ansible/galaxy/role.py +31 -13
- ansible/galaxy/token.py +2 -2
- ansible/inventory/group.py +1 -1
- ansible/inventory/manager.py +1 -1
- ansible/module_utils/ansible_release.py +2 -2
- ansible/module_utils/basic.py +11 -41
- ansible/module_utils/common/file.py +0 -100
- ansible/module_utils/common/json.py +1 -1
- ansible/module_utils/common/locale.py +1 -1
- ansible/module_utils/common/text/converters.py +2 -2
- ansible/module_utils/common/validation.py +1 -1
- ansible/module_utils/compat/_selectors2.py +4 -4
- ansible/module_utils/compat/datetime.py +40 -0
- ansible/module_utils/compat/selinux.py +1 -1
- ansible/module_utils/compat/typing.py +1 -1
- ansible/module_utils/connection.py +1 -1
- ansible/module_utils/facts/hardware/linux.py +2 -2
- ansible/module_utils/facts/hardware/openbsd.py +1 -1
- ansible/module_utils/facts/network/linux.py +3 -3
- ansible/module_utils/facts/other/facter.py +8 -15
- ansible/module_utils/facts/sysctl.py +1 -1
- ansible/module_utils/facts/system/date_time.py +2 -2
- ansible/module_utils/facts/system/distribution.py +1 -1
- ansible/module_utils/facts/system/local.py +6 -2
- ansible/module_utils/facts/system/pkg_mgr.py +6 -1
- ansible/module_utils/facts/system/service_mgr.py +4 -2
- ansible/module_utils/parsing/convert_bool.py +1 -1
- ansible/module_utils/service.py +9 -6
- ansible/module_utils/urls.py +40 -22
- ansible/modules/add_host.py +2 -2
- ansible/modules/apt.py +48 -31
- ansible/modules/apt_key.py +4 -4
- ansible/modules/apt_repository.py +5 -5
- ansible/modules/assemble.py +7 -7
- ansible/modules/assert.py +1 -1
- ansible/modules/async_status.py +11 -7
- ansible/modules/async_wrapper.py +1 -1
- ansible/modules/blockinfile.py +60 -17
- ansible/modules/command.py +37 -15
- ansible/modules/copy.py +35 -30
- ansible/modules/cron.py +14 -14
- ansible/modules/deb822_repository.py +4 -3
- ansible/modules/debconf.py +35 -14
- ansible/modules/debug.py +1 -1
- ansible/modules/dnf.py +29 -27
- ansible/modules/dnf5.py +22 -22
- ansible/modules/dpkg_selections.py +9 -2
- ansible/modules/expect.py +4 -4
- ansible/modules/fetch.py +7 -7
- ansible/modules/file.py +30 -30
- ansible/modules/find.py +82 -22
- ansible/modules/gather_facts.py +6 -2
- ansible/modules/get_url.py +29 -29
- ansible/modules/getent.py +4 -4
- ansible/modules/git.py +27 -27
- ansible/modules/group.py +5 -12
- ansible/modules/hostname.py +21 -2
- ansible/modules/include_role.py +5 -5
- ansible/modules/include_tasks.py +2 -2
- ansible/modules/include_vars.py +5 -5
- ansible/modules/iptables.py +70 -65
- ansible/modules/known_hosts.py +7 -7
- ansible/modules/lineinfile.py +33 -33
- ansible/modules/meta.py +13 -13
- ansible/modules/package.py +8 -8
- ansible/modules/package_facts.py +3 -3
- ansible/modules/pause.py +2 -2
- ansible/modules/ping.py +5 -5
- ansible/modules/pip.py +80 -46
- ansible/modules/reboot.py +8 -4
- ansible/modules/replace.py +20 -15
- ansible/modules/rpm_key.py +2 -2
- ansible/modules/script.py +16 -10
- ansible/modules/service.py +26 -98
- ansible/modules/service_facts.py +36 -12
- ansible/modules/set_fact.py +2 -2
- ansible/modules/set_stats.py +2 -2
- ansible/modules/setup.py +18 -18
- ansible/modules/shell.py +3 -3
- ansible/modules/stat.py +9 -30
- ansible/modules/subversion.py +9 -9
- ansible/modules/systemd.py +20 -19
- ansible/modules/systemd_service.py +20 -19
- ansible/modules/sysvinit.py +26 -21
- ansible/modules/tempfile.py +5 -4
- ansible/modules/template.py +60 -6
- ansible/modules/unarchive.py +21 -18
- ansible/modules/uri.py +39 -39
- ansible/modules/user.py +81 -53
- ansible/modules/wait_for.py +22 -21
- ansible/modules/wait_for_connection.py +4 -4
- ansible/modules/yum.py +38 -38
- ansible/modules/yum_repository.py +58 -80
- ansible/parsing/dataloader.py +27 -27
- ansible/parsing/mod_args.py +1 -1
- ansible/parsing/plugin_docs.py +3 -3
- ansible/parsing/splitter.py +14 -16
- ansible/parsing/utils/yaml.py +1 -1
- ansible/parsing/vault/__init__.py +8 -6
- ansible/parsing/yaml/constructor.py +1 -1
- ansible/parsing/yaml/objects.py +1 -1
- ansible/playbook/__init__.py +1 -1
- ansible/playbook/base.py +2 -2
- ansible/playbook/block.py +0 -1
- ansible/playbook/conditional.py +40 -114
- ansible/playbook/helpers.py +5 -28
- ansible/playbook/included_file.py +8 -7
- ansible/playbook/play.py +1 -1
- ansible/playbook/play_context.py +2 -2
- ansible/playbook/playbook_include.py +2 -2
- ansible/playbook/role/__init__.py +1 -1
- ansible/playbook/role/include.py +1 -1
- ansible/playbook/role/metadata.py +1 -1
- ansible/playbook/role_include.py +1 -1
- ansible/playbook/task.py +2 -2
- ansible/playbook/task_include.py +1 -24
- ansible/plugins/__init__.py +13 -5
- ansible/plugins/action/__init__.py +17 -43
- ansible/plugins/action/add_host.py +2 -3
- ansible/plugins/action/assemble.py +1 -1
- ansible/plugins/action/assert.py +2 -1
- ansible/plugins/action/copy.py +2 -2
- ansible/plugins/action/debug.py +2 -1
- ansible/plugins/action/fail.py +1 -0
- ansible/plugins/action/fetch.py +3 -1
- ansible/plugins/action/gather_facts.py +37 -13
- ansible/plugins/action/group_by.py +1 -0
- ansible/plugins/action/include_vars.py +3 -2
- ansible/plugins/action/normal.py +3 -3
- ansible/plugins/action/pause.py +1 -1
- ansible/plugins/action/reboot.py +21 -16
- ansible/plugins/action/script.py +23 -8
- ansible/plugins/action/set_fact.py +1 -0
- ansible/plugins/action/set_stats.py +1 -0
- ansible/plugins/action/shell.py +6 -0
- ansible/plugins/action/template.py +1 -1
- ansible/plugins/action/unarchive.py +1 -1
- ansible/plugins/action/uri.py +1 -1
- ansible/plugins/action/validate_argument_spec.py +1 -0
- ansible/plugins/action/wait_for_connection.py +4 -4
- ansible/plugins/become/__init__.py +1 -1
- ansible/plugins/become/su.py +1 -1
- ansible/plugins/cache/__init__.py +1 -1
- ansible/plugins/callback/junit.py +1 -1
- ansible/plugins/callback/oneline.py +1 -1
- ansible/plugins/callback/tree.py +1 -1
- ansible/plugins/cliconf/__init__.py +2 -2
- ansible/plugins/connection/__init__.py +65 -37
- ansible/plugins/connection/local.py +9 -8
- ansible/plugins/connection/paramiko_ssh.py +34 -28
- ansible/plugins/connection/psrp.py +56 -43
- ansible/plugins/connection/ssh.py +67 -43
- ansible/plugins/connection/winrm.py +77 -30
- ansible/plugins/doc_fragments/constructed.py +4 -4
- ansible/plugins/doc_fragments/files.py +12 -12
- ansible/plugins/doc_fragments/inventory_cache.py +0 -6
- ansible/plugins/doc_fragments/result_format_callback.py +5 -5
- ansible/plugins/doc_fragments/shell_common.py +2 -2
- ansible/plugins/doc_fragments/shell_windows.py +1 -1
- ansible/plugins/doc_fragments/template_common.py +6 -6
- ansible/plugins/doc_fragments/url.py +10 -10
- ansible/plugins/doc_fragments/url_windows.py +15 -15
- ansible/plugins/doc_fragments/vars_plugin_staging.py +4 -4
- ansible/plugins/filter/b64decode.yml +1 -1
- ansible/plugins/filter/b64encode.yml +2 -2
- ansible/plugins/filter/bool.yml +5 -5
- ansible/plugins/filter/combine.yml +1 -1
- ansible/plugins/filter/commonpath.yml +2 -1
- ansible/plugins/filter/core.py +6 -8
- ansible/plugins/filter/dict2items.yml +11 -1
- ansible/plugins/filter/difference.yml +1 -0
- ansible/plugins/filter/encryption.py +1 -1
- ansible/plugins/filter/extract.yml +1 -1
- ansible/plugins/filter/flatten.yml +1 -1
- ansible/plugins/filter/from_yaml.yml +1 -1
- ansible/plugins/filter/from_yaml_all.yml +2 -2
- ansible/plugins/filter/hash.yml +1 -1
- ansible/plugins/filter/human_readable.yml +1 -1
- ansible/plugins/filter/human_to_bytes.yml +2 -2
- ansible/plugins/filter/intersect.yml +1 -0
- ansible/plugins/filter/mandatory.yml +7 -0
- ansible/plugins/filter/mathstuff.py +15 -17
- ansible/plugins/filter/normpath.yml +1 -1
- ansible/plugins/filter/path_join.yml +8 -1
- ansible/plugins/filter/realpath.yml +3 -2
- ansible/plugins/filter/regex_findall.yml +8 -2
- ansible/plugins/filter/regex_replace.yml +9 -3
- ansible/plugins/filter/regex_search.yml +8 -2
- ansible/plugins/filter/relpath.yml +2 -2
- ansible/plugins/filter/root.yml +1 -1
- ansible/plugins/filter/splitext.yml +1 -1
- ansible/plugins/filter/subelements.yml +2 -2
- ansible/plugins/filter/symmetric_difference.yml +1 -0
- ansible/plugins/filter/ternary.yml +5 -5
- ansible/plugins/filter/to_json.yml +7 -7
- ansible/plugins/filter/to_nice_json.yml +5 -5
- ansible/plugins/filter/to_yaml.yml +2 -2
- ansible/plugins/filter/type_debug.yml +1 -1
- ansible/plugins/filter/union.yml +1 -0
- ansible/plugins/filter/unvault.yml +2 -2
- ansible/plugins/filter/urldecode.yml +13 -32
- ansible/plugins/filter/urlsplit.py +1 -1
- ansible/plugins/filter/vault.yml +1 -1
- ansible/plugins/filter/zip.yml +1 -1
- ansible/plugins/filter/zip_longest.yml +1 -1
- ansible/plugins/inventory/__init__.py +1 -1
- ansible/plugins/inventory/advanced_host_list.py +1 -1
- ansible/plugins/inventory/constructed.py +2 -2
- ansible/plugins/inventory/host_list.py +1 -1
- ansible/plugins/inventory/ini.py +6 -3
- ansible/plugins/inventory/script.py +8 -2
- ansible/plugins/inventory/toml.py +1 -1
- ansible/plugins/inventory/yaml.py +1 -1
- ansible/plugins/list.py +21 -17
- ansible/plugins/loader.py +66 -88
- ansible/plugins/lookup/__init__.py +1 -1
- ansible/plugins/lookup/config.py +16 -6
- ansible/plugins/lookup/csvfile.py +7 -4
- ansible/plugins/lookup/env.py +1 -1
- ansible/plugins/lookup/file.py +5 -2
- ansible/plugins/lookup/fileglob.py +5 -2
- ansible/plugins/lookup/first_found.py +20 -14
- ansible/plugins/lookup/ini.py +6 -3
- ansible/plugins/lookup/lines.py +2 -1
- ansible/plugins/lookup/password.py +7 -7
- ansible/plugins/lookup/pipe.py +1 -0
- ansible/plugins/lookup/random_choice.py +2 -2
- ansible/plugins/lookup/sequence.py +1 -1
- ansible/plugins/lookup/subelements.py +2 -2
- ansible/plugins/lookup/template.py +4 -1
- ansible/plugins/lookup/unvault.py +4 -1
- ansible/plugins/lookup/url.py +6 -6
- ansible/plugins/lookup/varnames.py +1 -1
- ansible/plugins/netconf/__init__.py +3 -3
- ansible/plugins/shell/__init__.py +1 -1
- ansible/plugins/shell/cmd.py +7 -7
- ansible/plugins/shell/powershell.py +1 -1
- ansible/plugins/strategy/__init__.py +8 -10
- ansible/plugins/strategy/free.py +1 -1
- ansible/plugins/strategy/linear.py +3 -3
- ansible/plugins/terminal/__init__.py +2 -2
- ansible/plugins/test/abs.yml +1 -1
- ansible/plugins/test/all.yml +1 -1
- ansible/plugins/test/any.yml +1 -1
- ansible/plugins/test/change.yml +2 -2
- ansible/plugins/test/changed.yml +2 -2
- ansible/plugins/test/contains.yml +1 -1
- ansible/plugins/test/core.py +1 -1
- ansible/plugins/test/directory.yml +1 -1
- ansible/plugins/test/exists.yml +3 -2
- ansible/plugins/test/failed.yml +2 -2
- ansible/plugins/test/failure.yml +2 -2
- ansible/plugins/test/falsy.yml +2 -2
- ansible/plugins/test/file.yml +1 -1
- ansible/plugins/test/finished.yml +2 -2
- ansible/plugins/test/is_abs.yml +1 -1
- ansible/plugins/test/is_dir.yml +1 -1
- ansible/plugins/test/is_file.yml +1 -1
- ansible/plugins/test/is_link.yml +1 -1
- ansible/plugins/test/is_mount.yml +1 -1
- ansible/plugins/test/is_same_file.yml +1 -1
- ansible/plugins/test/isnan.yml +1 -1
- ansible/plugins/test/issubset.yml +1 -2
- ansible/plugins/test/issuperset.yml +1 -2
- ansible/plugins/test/link.yml +1 -1
- ansible/plugins/test/link_exists.yml +1 -1
- ansible/plugins/test/match.yml +2 -2
- ansible/plugins/test/mount.yml +1 -1
- ansible/plugins/test/nan.yml +1 -1
- ansible/plugins/test/reachable.yml +2 -2
- ansible/plugins/test/regex.yml +1 -1
- ansible/plugins/test/same_file.yml +1 -1
- ansible/plugins/test/search.yml +2 -2
- ansible/plugins/test/skip.yml +3 -3
- ansible/plugins/test/skipped.yml +3 -3
- ansible/plugins/test/started.yml +2 -2
- ansible/plugins/test/subset.yml +1 -2
- ansible/plugins/test/succeeded.yml +2 -2
- ansible/plugins/test/success.yml +2 -2
- ansible/plugins/test/successful.yml +2 -2
- ansible/plugins/test/superset.yml +1 -2
- ansible/plugins/test/truthy.yml +3 -3
- ansible/plugins/test/unreachable.yml +2 -2
- ansible/plugins/test/uri.yml +1 -1
- ansible/plugins/test/url.yml +1 -1
- ansible/plugins/test/urn.yml +1 -1
- ansible/plugins/test/vault_encrypted.yml +1 -1
- ansible/plugins/test/version.yml +7 -7
- ansible/plugins/test/version_compare.yml +7 -7
- ansible/plugins/vars/host_group_vars.py +1 -1
- ansible/release.py +2 -2
- ansible/template/__init__.py +24 -26
- ansible/template/native_helpers.py +1 -1
- ansible/template/vars.py +1 -1
- ansible/utils/_junit_xml.py +1 -1
- ansible/utils/cmd_functions.py +1 -1
- ansible/utils/collection_loader/_collection_finder.py +12 -1
- ansible/utils/display.py +113 -62
- ansible/utils/encrypt.py +11 -14
- ansible/utils/hashing.py +1 -1
- ansible/utils/jsonrpc.py +1 -1
- ansible/utils/path.py +1 -1
- ansible/utils/plugin_docs.py +1 -1
- ansible/utils/py3compat.py +1 -1
- ansible/utils/shlex.py +2 -10
- ansible/utils/ssh_functions.py +5 -4
- ansible/utils/unicode.py +1 -1
- ansible/utils/unsafe_proxy.py +1 -1
- ansible/utils/vars.py +4 -29
- ansible/vars/hostvars.py +1 -2
- ansible/vars/manager.py +13 -9
- ansible/vars/plugins.py +2 -2
- {ansible_core-2.15.4rc1.dist-info → ansible_core-2.16.0b2.dist-info}/COPYING +4 -5
- {ansible_core-2.15.4rc1.dist-info → ansible_core-2.16.0b2.dist-info}/METADATA +2 -4
- {ansible_core-2.15.4rc1.dist-info → ansible_core-2.16.0b2.dist-info}/RECORD +424 -425
- ansible_test/_data/completion/docker.txt +9 -9
- ansible_test/_data/completion/remote.txt +4 -7
- ansible_test/_data/completion/windows.txt +0 -2
- ansible_test/_data/requirements/ansible-test.txt +2 -1
- ansible_test/_data/requirements/ansible.txt +0 -3
- ansible_test/_data/requirements/constraints.txt +0 -2
- ansible_test/_data/requirements/sanity.ansible-doc.txt +3 -5
- ansible_test/_data/requirements/sanity.changelog.in +1 -2
- ansible_test/_data/requirements/sanity.changelog.txt +4 -6
- ansible_test/_data/requirements/sanity.import.plugin.txt +2 -4
- ansible_test/_data/requirements/sanity.import.txt +1 -3
- ansible_test/_data/requirements/sanity.integration-aliases.txt +1 -3
- ansible_test/_data/requirements/sanity.mypy.txt +12 -12
- ansible_test/_data/requirements/sanity.pep8.txt +1 -1
- ansible_test/_data/requirements/sanity.pylint.txt +6 -12
- ansible_test/_data/requirements/sanity.runtime-metadata.txt +1 -3
- ansible_test/_data/requirements/sanity.validate-modules.in +1 -1
- ansible_test/_data/requirements/sanity.validate-modules.txt +3 -5
- ansible_test/_data/requirements/sanity.yamllint.txt +3 -5
- ansible_test/_data/requirements/units.txt +0 -1
- ansible_test/_internal/ci/azp.py +4 -4
- ansible_test/_internal/cli/environments.py +0 -13
- ansible_test/_internal/commands/coverage/analyze/targets/__init__.py +4 -4
- ansible_test/_internal/commands/coverage/combine.py +1 -1
- ansible_test/_internal/commands/integration/cloud/acme.py +6 -8
- ansible_test/_internal/commands/integration/cloud/cs.py +4 -9
- ansible_test/_internal/commands/integration/cloud/galaxy.py +103 -96
- ansible_test/_internal/commands/integration/cloud/httptester.py +0 -3
- ansible_test/_internal/commands/integration/cloud/nios.py +7 -9
- ansible_test/_internal/commands/integration/cloud/openshift.py +2 -7
- ansible_test/_internal/commands/integration/cloud/vcenter.py +11 -95
- ansible_test/_internal/commands/sanity/__init__.py +10 -0
- ansible_test/_internal/commands/sanity/import.py +8 -2
- ansible_test/_internal/commands/sanity/pylint.py +27 -1
- ansible_test/_internal/commands/units/__init__.py +2 -1
- ansible_test/_internal/config.py +0 -7
- ansible_test/_internal/containers.py +11 -56
- ansible_test/_internal/core_ci.py +0 -7
- ansible_test/_internal/coverage_util.py +8 -3
- ansible_test/_internal/delegation.py +0 -1
- ansible_test/_internal/diff.py +1 -1
- ansible_test/_internal/docker_util.py +9 -2
- ansible_test/_internal/host_profiles.py +6 -6
- ansible_test/_internal/http.py +1 -1
- ansible_test/_internal/junit_xml.py +1 -1
- ansible_test/_internal/pypi_proxy.py +1 -1
- ansible_test/_internal/python_requirements.py +3 -8
- ansible_test/_internal/util.py +1 -6
- ansible_test/_util/controller/sanity/code-smell/no-get-exception.json +4 -0
- ansible_test/_util/controller/sanity/code-smell/replace-urlopen.json +4 -0
- ansible_test/_util/controller/sanity/code-smell/use-compat-six.json +4 -0
- ansible_test/_util/controller/sanity/mypy/ansible-core.ini +3 -0
- ansible_test/_util/controller/sanity/pylint/config/ansible-test-target.cfg +2 -0
- ansible_test/_util/controller/sanity/pylint/config/ansible-test.cfg +0 -1
- ansible_test/_util/controller/sanity/pylint/config/collection.cfg +1 -0
- ansible_test/_util/controller/sanity/pylint/plugins/deprecated.py +172 -10
- ansible_test/_util/controller/sanity/pylint/plugins/string_format.py +13 -2
- ansible_test/_util/controller/sanity/pylint/plugins/unwanted.py +7 -1
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py +6 -6
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/module_args.py +1 -1
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/utils.py +1 -1
- ansible_test/_util/controller/sanity/yamllint/yamllinter.py +3 -3
- ansible_test/_util/controller/tools/collection_detail.py +2 -2
- ansible_test/_util/target/common/constants.py +2 -2
- ansible_test/_util/target/pytest/plugins/ansible_forked.py +103 -0
- ansible_test/_util/target/sanity/import/importer.py +0 -8
- ansible_test/_util/target/setup/bootstrap.sh +36 -16
- ansible_test/_util/target/setup/quiet_pip.py +0 -4
- ansible/modules/_include.py +0 -80
- ansible_test/_internal/commands/integration/cloud/foreman.py +0 -102
- ansible_test/_util/target/setup/ConfigureRemotingForAnsible.ps1 +0 -435
- {ansible_core-2.15.4rc1.data → ansible_core-2.16.0b2.data}/scripts/ansible-test +0 -0
- {ansible_core-2.15.4rc1.dist-info → ansible_core-2.16.0b2.dist-info}/WHEEL +0 -0
- {ansible_core-2.15.4rc1.dist-info → ansible_core-2.16.0b2.dist-info}/entry_points.txt +0 -0
- {ansible_core-2.15.4rc1.dist-info → ansible_core-2.16.0b2.dist-info}/top_level.txt +0 -0
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
# (c) 2015 Toshio Kuratomi <tkuratomi@ansible.com>
|
|
3
3
|
# (c) 2017, Peter Sprygada <psprygad@redhat.com>
|
|
4
4
|
# (c) 2017 Ansible Project
|
|
5
|
-
from __future__ import (absolute_import, division, print_function)
|
|
5
|
+
from __future__ import (annotations, absolute_import, division, print_function)
|
|
6
6
|
__metaclass__ = type
|
|
7
7
|
|
|
8
|
+
import collections.abc as c
|
|
8
9
|
import fcntl
|
|
10
|
+
import io
|
|
9
11
|
import os
|
|
10
12
|
import shlex
|
|
11
13
|
import typing as t
|
|
@@ -14,8 +16,11 @@ from abc import abstractmethod
|
|
|
14
16
|
from functools import wraps
|
|
15
17
|
|
|
16
18
|
from ansible import constants as C
|
|
17
|
-
from ansible.module_utils.
|
|
19
|
+
from ansible.module_utils.common.text.converters import to_bytes, to_text
|
|
20
|
+
from ansible.playbook.play_context import PlayContext
|
|
18
21
|
from ansible.plugins import AnsiblePlugin
|
|
22
|
+
from ansible.plugins.become import BecomeBase
|
|
23
|
+
from ansible.plugins.shell import ShellBase
|
|
19
24
|
from ansible.utils.display import Display
|
|
20
25
|
from ansible.plugins.loader import connection_loader, get_shell_plugin
|
|
21
26
|
from ansible.utils.path import unfrackpath
|
|
@@ -27,10 +32,15 @@ __all__ = ['ConnectionBase', 'ensure_connect']
|
|
|
27
32
|
|
|
28
33
|
BUFSIZE = 65536
|
|
29
34
|
|
|
35
|
+
P = t.ParamSpec('P')
|
|
36
|
+
T = t.TypeVar('T')
|
|
30
37
|
|
|
31
|
-
|
|
38
|
+
|
|
39
|
+
def ensure_connect(
|
|
40
|
+
func: c.Callable[t.Concatenate[ConnectionBase, P], T],
|
|
41
|
+
) -> c.Callable[t.Concatenate[ConnectionBase, P], T]:
|
|
32
42
|
@wraps(func)
|
|
33
|
-
def wrapped(self, *args, **kwargs):
|
|
43
|
+
def wrapped(self: ConnectionBase, *args: P.args, **kwargs: P.kwargs) -> T:
|
|
34
44
|
if not self._connected:
|
|
35
45
|
self._connect()
|
|
36
46
|
return func(self, *args, **kwargs)
|
|
@@ -57,9 +67,16 @@ class ConnectionBase(AnsiblePlugin):
|
|
|
57
67
|
supports_persistence = False
|
|
58
68
|
force_persistence = False
|
|
59
69
|
|
|
60
|
-
default_user = None
|
|
70
|
+
default_user: str | None = None
|
|
61
71
|
|
|
62
|
-
def __init__(
|
|
72
|
+
def __init__(
|
|
73
|
+
self,
|
|
74
|
+
play_context: PlayContext,
|
|
75
|
+
new_stdin: io.TextIOWrapper | None = None,
|
|
76
|
+
shell: ShellBase | None = None,
|
|
77
|
+
*args: t.Any,
|
|
78
|
+
**kwargs: t.Any,
|
|
79
|
+
) -> None:
|
|
63
80
|
|
|
64
81
|
super(ConnectionBase, self).__init__()
|
|
65
82
|
|
|
@@ -77,7 +94,7 @@ class ConnectionBase(AnsiblePlugin):
|
|
|
77
94
|
self.success_key = None
|
|
78
95
|
self.prompt = None
|
|
79
96
|
self._connected = False
|
|
80
|
-
self._socket_path = None
|
|
97
|
+
self._socket_path: str | None = None
|
|
81
98
|
|
|
82
99
|
# helper plugins
|
|
83
100
|
self._shell = shell
|
|
@@ -87,10 +104,10 @@ class ConnectionBase(AnsiblePlugin):
|
|
|
87
104
|
shell_type = play_context.shell if play_context.shell else getattr(self, '_shell_type', None)
|
|
88
105
|
self._shell = get_shell_plugin(shell_type=shell_type, executable=self._play_context.executable)
|
|
89
106
|
|
|
90
|
-
self.become = None
|
|
107
|
+
self.become: BecomeBase | None = None
|
|
91
108
|
|
|
92
109
|
@property
|
|
93
|
-
def _new_stdin(self):
|
|
110
|
+
def _new_stdin(self) -> io.TextIOWrapper | None:
|
|
94
111
|
display.deprecated(
|
|
95
112
|
"The connection's stdin object is deprecated. "
|
|
96
113
|
"Call display.prompt_until(msg) instead.",
|
|
@@ -98,21 +115,21 @@ class ConnectionBase(AnsiblePlugin):
|
|
|
98
115
|
)
|
|
99
116
|
return self.__new_stdin
|
|
100
117
|
|
|
101
|
-
def set_become_plugin(self, plugin):
|
|
118
|
+
def set_become_plugin(self, plugin: BecomeBase) -> None:
|
|
102
119
|
self.become = plugin
|
|
103
120
|
|
|
104
121
|
@property
|
|
105
|
-
def connected(self):
|
|
122
|
+
def connected(self) -> bool:
|
|
106
123
|
'''Read-only property holding whether the connection to the remote host is active or closed.'''
|
|
107
124
|
return self._connected
|
|
108
125
|
|
|
109
126
|
@property
|
|
110
|
-
def socket_path(self):
|
|
127
|
+
def socket_path(self) -> str | None:
|
|
111
128
|
'''Read-only property holding the connection socket path for this remote host'''
|
|
112
129
|
return self._socket_path
|
|
113
130
|
|
|
114
131
|
@staticmethod
|
|
115
|
-
def _split_ssh_args(argstring):
|
|
132
|
+
def _split_ssh_args(argstring: str) -> list[str]:
|
|
116
133
|
"""
|
|
117
134
|
Takes a string like '-o Foo=1 -o Bar="foo bar"' and returns a
|
|
118
135
|
list ['-o', 'Foo=1', '-o', 'Bar=foo bar'] that can be added to
|
|
@@ -123,17 +140,17 @@ class ConnectionBase(AnsiblePlugin):
|
|
|
123
140
|
|
|
124
141
|
@property
|
|
125
142
|
@abstractmethod
|
|
126
|
-
def transport(self):
|
|
143
|
+
def transport(self) -> str:
|
|
127
144
|
"""String used to identify this Connection class from other classes"""
|
|
128
145
|
pass
|
|
129
146
|
|
|
130
147
|
@abstractmethod
|
|
131
|
-
def _connect(self):
|
|
148
|
+
def _connect(self: T) -> T:
|
|
132
149
|
"""Connect to the host we've been initialized with"""
|
|
133
150
|
|
|
134
151
|
@ensure_connect
|
|
135
152
|
@abstractmethod
|
|
136
|
-
def exec_command(self, cmd, in_data=None, sudoable=True):
|
|
153
|
+
def exec_command(self, cmd: str, in_data: bytes | None = None, sudoable: bool = True) -> tuple[int, bytes, bytes]:
|
|
137
154
|
"""Run a command on the remote host.
|
|
138
155
|
|
|
139
156
|
:arg cmd: byte string containing the command
|
|
@@ -201,36 +218,36 @@ class ConnectionBase(AnsiblePlugin):
|
|
|
201
218
|
|
|
202
219
|
@ensure_connect
|
|
203
220
|
@abstractmethod
|
|
204
|
-
def put_file(self, in_path, out_path):
|
|
221
|
+
def put_file(self, in_path: str, out_path: str) -> None:
|
|
205
222
|
"""Transfer a file from local to remote"""
|
|
206
223
|
pass
|
|
207
224
|
|
|
208
225
|
@ensure_connect
|
|
209
226
|
@abstractmethod
|
|
210
|
-
def fetch_file(self, in_path, out_path):
|
|
227
|
+
def fetch_file(self, in_path: str, out_path: str) -> None:
|
|
211
228
|
"""Fetch a file from remote to local; callers are expected to have pre-created the directory chain for out_path"""
|
|
212
229
|
pass
|
|
213
230
|
|
|
214
231
|
@abstractmethod
|
|
215
|
-
def close(self):
|
|
232
|
+
def close(self) -> None:
|
|
216
233
|
"""Terminate the connection"""
|
|
217
234
|
pass
|
|
218
235
|
|
|
219
|
-
def connection_lock(self):
|
|
236
|
+
def connection_lock(self) -> None:
|
|
220
237
|
f = self._play_context.connection_lockfd
|
|
221
238
|
display.vvvv('CONNECTION: pid %d waiting for lock on %d' % (os.getpid(), f), host=self._play_context.remote_addr)
|
|
222
239
|
fcntl.lockf(f, fcntl.LOCK_EX)
|
|
223
240
|
display.vvvv('CONNECTION: pid %d acquired lock on %d' % (os.getpid(), f), host=self._play_context.remote_addr)
|
|
224
241
|
|
|
225
|
-
def connection_unlock(self):
|
|
242
|
+
def connection_unlock(self) -> None:
|
|
226
243
|
f = self._play_context.connection_lockfd
|
|
227
244
|
fcntl.lockf(f, fcntl.LOCK_UN)
|
|
228
245
|
display.vvvv('CONNECTION: pid %d released lock on %d' % (os.getpid(), f), host=self._play_context.remote_addr)
|
|
229
246
|
|
|
230
|
-
def reset(self):
|
|
247
|
+
def reset(self) -> None:
|
|
231
248
|
display.warning("Reset is not implemented for this connection")
|
|
232
249
|
|
|
233
|
-
def update_vars(self, variables):
|
|
250
|
+
def update_vars(self, variables: dict[str, t.Any]) -> None:
|
|
234
251
|
'''
|
|
235
252
|
Adds 'magic' variables relating to connections to the variable dictionary provided.
|
|
236
253
|
In case users need to access from the play, this is a legacy from runner.
|
|
@@ -246,7 +263,7 @@ class ConnectionBase(AnsiblePlugin):
|
|
|
246
263
|
elif varname == 'ansible_connection':
|
|
247
264
|
# its me mom!
|
|
248
265
|
value = self._load_name
|
|
249
|
-
elif varname == 'ansible_shell_type':
|
|
266
|
+
elif varname == 'ansible_shell_type' and self._shell:
|
|
250
267
|
# its my cousin ...
|
|
251
268
|
value = self._shell._load_name
|
|
252
269
|
else:
|
|
@@ -279,9 +296,15 @@ class NetworkConnectionBase(ConnectionBase):
|
|
|
279
296
|
# Do not use _remote_is_local in other connections
|
|
280
297
|
_remote_is_local = True
|
|
281
298
|
|
|
282
|
-
def __init__(
|
|
299
|
+
def __init__(
|
|
300
|
+
self,
|
|
301
|
+
play_context: PlayContext,
|
|
302
|
+
new_stdin: io.TextIOWrapper | None = None,
|
|
303
|
+
*args: t.Any,
|
|
304
|
+
**kwargs: t.Any,
|
|
305
|
+
) -> None:
|
|
283
306
|
super(NetworkConnectionBase, self).__init__(play_context, new_stdin, *args, **kwargs)
|
|
284
|
-
self._messages = []
|
|
307
|
+
self._messages: list[tuple[str, str]] = []
|
|
285
308
|
self._conn_closed = False
|
|
286
309
|
|
|
287
310
|
self._network_os = self._play_context.network_os
|
|
@@ -289,7 +312,7 @@ class NetworkConnectionBase(ConnectionBase):
|
|
|
289
312
|
self._local = connection_loader.get('local', play_context, '/dev/null')
|
|
290
313
|
self._local.set_options()
|
|
291
314
|
|
|
292
|
-
self._sub_plugin = {}
|
|
315
|
+
self._sub_plugin: dict[str, t.Any] = {}
|
|
293
316
|
self._cached_variables = (None, None, None)
|
|
294
317
|
|
|
295
318
|
# reconstruct the socket_path and set instance values accordingly
|
|
@@ -308,10 +331,10 @@ class NetworkConnectionBase(ConnectionBase):
|
|
|
308
331
|
return method
|
|
309
332
|
raise AttributeError("'%s' object has no attribute '%s'" % (self.__class__.__name__, name))
|
|
310
333
|
|
|
311
|
-
def exec_command(self, cmd, in_data=None, sudoable=True):
|
|
334
|
+
def exec_command(self, cmd: str, in_data: bytes | None = None, sudoable: bool = True) -> tuple[int, bytes, bytes]:
|
|
312
335
|
return self._local.exec_command(cmd, in_data, sudoable)
|
|
313
336
|
|
|
314
|
-
def queue_message(self, level, message):
|
|
337
|
+
def queue_message(self, level: str, message: str) -> None:
|
|
315
338
|
"""
|
|
316
339
|
Adds a message to the queue of messages waiting to be pushed back to the controller process.
|
|
317
340
|
|
|
@@ -321,19 +344,19 @@ class NetworkConnectionBase(ConnectionBase):
|
|
|
321
344
|
"""
|
|
322
345
|
self._messages.append((level, message))
|
|
323
346
|
|
|
324
|
-
def pop_messages(self):
|
|
347
|
+
def pop_messages(self) -> list[tuple[str, str]]:
|
|
325
348
|
messages, self._messages = self._messages, []
|
|
326
349
|
return messages
|
|
327
350
|
|
|
328
|
-
def put_file(self, in_path, out_path):
|
|
351
|
+
def put_file(self, in_path: str, out_path: str) -> None:
|
|
329
352
|
"""Transfer a file from local to remote"""
|
|
330
353
|
return self._local.put_file(in_path, out_path)
|
|
331
354
|
|
|
332
|
-
def fetch_file(self, in_path, out_path):
|
|
355
|
+
def fetch_file(self, in_path: str, out_path: str) -> None:
|
|
333
356
|
"""Fetch a file from remote to local"""
|
|
334
357
|
return self._local.fetch_file(in_path, out_path)
|
|
335
358
|
|
|
336
|
-
def reset(self):
|
|
359
|
+
def reset(self) -> None:
|
|
337
360
|
'''
|
|
338
361
|
Reset the connection
|
|
339
362
|
'''
|
|
@@ -342,12 +365,17 @@ class NetworkConnectionBase(ConnectionBase):
|
|
|
342
365
|
self.close()
|
|
343
366
|
self.queue_message('vvvv', 'reset call on connection instance')
|
|
344
367
|
|
|
345
|
-
def close(self):
|
|
368
|
+
def close(self) -> None:
|
|
346
369
|
self._conn_closed = True
|
|
347
370
|
if self._connected:
|
|
348
371
|
self._connected = False
|
|
349
372
|
|
|
350
|
-
def set_options(
|
|
373
|
+
def set_options(
|
|
374
|
+
self,
|
|
375
|
+
task_keys: dict[str, t.Any] | None = None,
|
|
376
|
+
var_options: dict[str, t.Any] | None = None,
|
|
377
|
+
direct: dict[str, t.Any] | None = None,
|
|
378
|
+
) -> None:
|
|
351
379
|
super(NetworkConnectionBase, self).set_options(task_keys=task_keys, var_options=var_options, direct=direct)
|
|
352
380
|
if self.get_option('persistent_log_messages'):
|
|
353
381
|
warning = "Persistent connection logging is enabled for %s. This will log ALL interactions" % self._play_context.remote_addr
|
|
@@ -362,7 +390,7 @@ class NetworkConnectionBase(ConnectionBase):
|
|
|
362
390
|
except AttributeError:
|
|
363
391
|
pass
|
|
364
392
|
|
|
365
|
-
def _update_connection_state(self):
|
|
393
|
+
def _update_connection_state(self) -> None:
|
|
366
394
|
'''
|
|
367
395
|
Reconstruct the connection socket_path and check if it exists
|
|
368
396
|
|
|
@@ -385,6 +413,6 @@ class NetworkConnectionBase(ConnectionBase):
|
|
|
385
413
|
self._connected = True
|
|
386
414
|
self._socket_path = socket_path
|
|
387
415
|
|
|
388
|
-
def _log_messages(self, message):
|
|
416
|
+
def _log_messages(self, message: str) -> None:
|
|
389
417
|
if self.get_option('persistent_log_messages'):
|
|
390
418
|
self.queue_message('log', message)
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# (c) 2015, 2017 Toshio Kuratomi <tkuratomi@ansible.com>
|
|
3
3
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
4
4
|
|
|
5
|
-
from __future__ import (absolute_import, division, print_function)
|
|
5
|
+
from __future__ import (annotations, absolute_import, division, print_function)
|
|
6
6
|
__metaclass__ = type
|
|
7
7
|
|
|
8
8
|
DOCUMENTATION = '''
|
|
@@ -24,12 +24,13 @@ import os
|
|
|
24
24
|
import pty
|
|
25
25
|
import shutil
|
|
26
26
|
import subprocess
|
|
27
|
+
import typing as t
|
|
27
28
|
|
|
28
29
|
import ansible.constants as C
|
|
29
30
|
from ansible.errors import AnsibleError, AnsibleFileNotFound
|
|
30
31
|
from ansible.module_utils.compat import selectors
|
|
31
32
|
from ansible.module_utils.six import text_type, binary_type
|
|
32
|
-
from ansible.module_utils.
|
|
33
|
+
from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text
|
|
33
34
|
from ansible.plugins.connection import ConnectionBase
|
|
34
35
|
from ansible.utils.display import Display
|
|
35
36
|
from ansible.utils.path import unfrackpath
|
|
@@ -43,7 +44,7 @@ class Connection(ConnectionBase):
|
|
|
43
44
|
transport = 'local'
|
|
44
45
|
has_pipelining = True
|
|
45
46
|
|
|
46
|
-
def __init__(self, *args, **kwargs):
|
|
47
|
+
def __init__(self, *args: t.Any, **kwargs: t.Any) -> None:
|
|
47
48
|
|
|
48
49
|
super(Connection, self).__init__(*args, **kwargs)
|
|
49
50
|
self.cwd = None
|
|
@@ -53,7 +54,7 @@ class Connection(ConnectionBase):
|
|
|
53
54
|
display.vv("Current user (uid=%s) does not seem to exist on this system, leaving user empty." % os.getuid())
|
|
54
55
|
self.default_user = ""
|
|
55
56
|
|
|
56
|
-
def _connect(self):
|
|
57
|
+
def _connect(self) -> Connection:
|
|
57
58
|
''' connect to the local host; nothing to do here '''
|
|
58
59
|
|
|
59
60
|
# Because we haven't made any remote connection we're running as
|
|
@@ -65,7 +66,7 @@ class Connection(ConnectionBase):
|
|
|
65
66
|
self._connected = True
|
|
66
67
|
return self
|
|
67
68
|
|
|
68
|
-
def exec_command(self, cmd, in_data=None, sudoable=True):
|
|
69
|
+
def exec_command(self, cmd: str, in_data: bytes | None = None, sudoable: bool = True) -> tuple[int, bytes, bytes]:
|
|
69
70
|
''' run a command on the local host '''
|
|
70
71
|
|
|
71
72
|
super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable)
|
|
@@ -163,7 +164,7 @@ class Connection(ConnectionBase):
|
|
|
163
164
|
display.debug("done with local.exec_command()")
|
|
164
165
|
return (p.returncode, stdout, stderr)
|
|
165
166
|
|
|
166
|
-
def put_file(self, in_path, out_path):
|
|
167
|
+
def put_file(self, in_path: str, out_path: str) -> None:
|
|
167
168
|
''' transfer a file from local to local '''
|
|
168
169
|
|
|
169
170
|
super(Connection, self).put_file(in_path, out_path)
|
|
@@ -181,7 +182,7 @@ class Connection(ConnectionBase):
|
|
|
181
182
|
except IOError as e:
|
|
182
183
|
raise AnsibleError("failed to transfer file to {0}: {1}".format(to_native(out_path), to_native(e)))
|
|
183
184
|
|
|
184
|
-
def fetch_file(self, in_path, out_path):
|
|
185
|
+
def fetch_file(self, in_path: str, out_path: str) -> None:
|
|
185
186
|
''' fetch a file from local to local -- for compatibility '''
|
|
186
187
|
|
|
187
188
|
super(Connection, self).fetch_file(in_path, out_path)
|
|
@@ -189,6 +190,6 @@ class Connection(ConnectionBase):
|
|
|
189
190
|
display.vvv(u"FETCH {0} TO {1}".format(in_path, out_path), host=self._play_context.remote_addr)
|
|
190
191
|
self.put_file(in_path, out_path)
|
|
191
192
|
|
|
192
|
-
def close(self):
|
|
193
|
+
def close(self) -> None:
|
|
193
194
|
''' terminate the connection; nothing to do here '''
|
|
194
195
|
self._connected = False
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
# (c) 2012, Michael DeHaan <michael.dehaan@gmail.com>
|
|
2
2
|
# (c) 2017 Ansible Project
|
|
3
3
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
4
|
-
from __future__ import (absolute_import, division, print_function)
|
|
4
|
+
from __future__ import (annotations, absolute_import, division, print_function)
|
|
5
5
|
__metaclass__ = type
|
|
6
6
|
|
|
7
7
|
DOCUMENTATION = """
|
|
8
8
|
author: Ansible Core Team
|
|
9
9
|
name: paramiko
|
|
10
|
-
short_description: Run tasks via
|
|
10
|
+
short_description: Run tasks via Python SSH (paramiko)
|
|
11
11
|
description:
|
|
12
|
-
- Use the
|
|
12
|
+
- Use the Python SSH implementation (Paramiko) to connect to targets
|
|
13
13
|
- The paramiko transport is provided because many distributions, in particular EL6 and before do not support ControlPersist
|
|
14
14
|
in their SSH implementations.
|
|
15
15
|
- This is needed on the Ansible control machine to be reasonably efficient with connections.
|
|
@@ -86,7 +86,7 @@ DOCUMENTATION = """
|
|
|
86
86
|
description:
|
|
87
87
|
- Whether or not to enable RSA SHA2 algorithms for pubkeys and hostkeys
|
|
88
88
|
- On paramiko versions older than 2.9, this only affects hostkeys
|
|
89
|
-
- For behavior matching paramiko<2.9 set this to
|
|
89
|
+
- For behavior matching paramiko<2.9 set this to V(False)
|
|
90
90
|
vars:
|
|
91
91
|
- name: ansible_paramiko_use_rsa_sha2_algorithms
|
|
92
92
|
ini:
|
|
@@ -293,6 +293,7 @@ import tempfile
|
|
|
293
293
|
import traceback
|
|
294
294
|
import fcntl
|
|
295
295
|
import re
|
|
296
|
+
import typing as t
|
|
296
297
|
|
|
297
298
|
from ansible.module_utils.compat.version import LooseVersion
|
|
298
299
|
from binascii import hexlify
|
|
@@ -307,7 +308,7 @@ from ansible.module_utils.compat.paramiko import PARAMIKO_IMPORT_ERR, paramiko
|
|
|
307
308
|
from ansible.plugins.connection import ConnectionBase
|
|
308
309
|
from ansible.utils.display import Display
|
|
309
310
|
from ansible.utils.path import makedirs_safe
|
|
310
|
-
from ansible.module_utils.
|
|
311
|
+
from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text
|
|
311
312
|
|
|
312
313
|
display = Display()
|
|
313
314
|
|
|
@@ -321,8 +322,12 @@ Are you sure you want to continue connecting (yes/no)?
|
|
|
321
322
|
# SSH Options Regex
|
|
322
323
|
SETTINGS_REGEX = re.compile(r'(\w+)(?:\s*=\s*|\s+)(.+)')
|
|
323
324
|
|
|
325
|
+
MissingHostKeyPolicy: type = object
|
|
326
|
+
if paramiko:
|
|
327
|
+
MissingHostKeyPolicy = paramiko.MissingHostKeyPolicy
|
|
324
328
|
|
|
325
|
-
|
|
329
|
+
|
|
330
|
+
class MyAddPolicy(MissingHostKeyPolicy):
|
|
326
331
|
"""
|
|
327
332
|
Based on AutoAddPolicy in paramiko so we can determine when keys are added
|
|
328
333
|
|
|
@@ -332,11 +337,11 @@ class MyAddPolicy(object):
|
|
|
332
337
|
local L{HostKeys} object, and saving it. This is used by L{SSHClient}.
|
|
333
338
|
"""
|
|
334
339
|
|
|
335
|
-
def __init__(self, connection):
|
|
340
|
+
def __init__(self, connection: Connection) -> None:
|
|
336
341
|
self.connection = connection
|
|
337
342
|
self._options = connection._options
|
|
338
343
|
|
|
339
|
-
def missing_host_key(self, client, hostname, key):
|
|
344
|
+
def missing_host_key(self, client, hostname, key) -> None:
|
|
340
345
|
|
|
341
346
|
if all((self.connection.get_option('host_key_checking'), not self.connection.get_option('host_key_auto_add'))):
|
|
342
347
|
|
|
@@ -367,20 +372,20 @@ class MyAddPolicy(object):
|
|
|
367
372
|
|
|
368
373
|
# keep connection objects on a per host basis to avoid repeated attempts to reconnect
|
|
369
374
|
|
|
370
|
-
SSH_CONNECTION_CACHE
|
|
371
|
-
SFTP_CONNECTION_CACHE
|
|
375
|
+
SSH_CONNECTION_CACHE: dict[str, paramiko.client.SSHClient] = {}
|
|
376
|
+
SFTP_CONNECTION_CACHE: dict[str, paramiko.sftp_client.SFTPClient] = {}
|
|
372
377
|
|
|
373
378
|
|
|
374
379
|
class Connection(ConnectionBase):
|
|
375
380
|
''' SSH based connections with Paramiko '''
|
|
376
381
|
|
|
377
382
|
transport = 'paramiko'
|
|
378
|
-
_log_channel = None
|
|
383
|
+
_log_channel: str | None = None
|
|
379
384
|
|
|
380
|
-
def _cache_key(self):
|
|
385
|
+
def _cache_key(self) -> str:
|
|
381
386
|
return "%s__%s__" % (self.get_option('remote_addr'), self.get_option('remote_user'))
|
|
382
387
|
|
|
383
|
-
def _connect(self):
|
|
388
|
+
def _connect(self) -> Connection:
|
|
384
389
|
cache_key = self._cache_key()
|
|
385
390
|
if cache_key in SSH_CONNECTION_CACHE:
|
|
386
391
|
self.ssh = SSH_CONNECTION_CACHE[cache_key]
|
|
@@ -390,11 +395,11 @@ class Connection(ConnectionBase):
|
|
|
390
395
|
self._connected = True
|
|
391
396
|
return self
|
|
392
397
|
|
|
393
|
-
def _set_log_channel(self, name):
|
|
398
|
+
def _set_log_channel(self, name: str) -> None:
|
|
394
399
|
'''Mimic paramiko.SSHClient.set_log_channel'''
|
|
395
400
|
self._log_channel = name
|
|
396
401
|
|
|
397
|
-
def _parse_proxy_command(self, port=22):
|
|
402
|
+
def _parse_proxy_command(self, port: int = 22) -> dict[str, t.Any]:
|
|
398
403
|
proxy_command = None
|
|
399
404
|
# Parse ansible_ssh_common_args, specifically looking for ProxyCommand
|
|
400
405
|
ssh_args = [
|
|
@@ -439,7 +444,7 @@ class Connection(ConnectionBase):
|
|
|
439
444
|
|
|
440
445
|
return sock_kwarg
|
|
441
446
|
|
|
442
|
-
def _connect_uncached(self):
|
|
447
|
+
def _connect_uncached(self) -> paramiko.SSHClient:
|
|
443
448
|
''' activates the connection object '''
|
|
444
449
|
|
|
445
450
|
if paramiko is None:
|
|
@@ -453,10 +458,11 @@ class Connection(ConnectionBase):
|
|
|
453
458
|
|
|
454
459
|
# Set pubkey and hostkey algorithms to disable, the only manipulation allowed currently
|
|
455
460
|
# is keeping or omitting rsa-sha2 algorithms
|
|
461
|
+
# default_keys: t.Tuple[str] = ()
|
|
456
462
|
paramiko_preferred_pubkeys = getattr(paramiko.Transport, '_preferred_pubkeys', ())
|
|
457
463
|
paramiko_preferred_hostkeys = getattr(paramiko.Transport, '_preferred_keys', ())
|
|
458
464
|
use_rsa_sha2_algorithms = self.get_option('use_rsa_sha2_algorithms')
|
|
459
|
-
disabled_algorithms = {}
|
|
465
|
+
disabled_algorithms: t.Dict[str, t.Iterable[str]] = {}
|
|
460
466
|
if not use_rsa_sha2_algorithms:
|
|
461
467
|
if paramiko_preferred_pubkeys:
|
|
462
468
|
disabled_algorithms['pubkeys'] = tuple(a for a in paramiko_preferred_pubkeys if 'rsa-sha2' in a)
|
|
@@ -533,7 +539,7 @@ class Connection(ConnectionBase):
|
|
|
533
539
|
|
|
534
540
|
return ssh
|
|
535
541
|
|
|
536
|
-
def exec_command(self, cmd, in_data=None, sudoable=True):
|
|
542
|
+
def exec_command(self, cmd: str, in_data: bytes | None = None, sudoable: bool = True) -> tuple[int, bytes, bytes]:
|
|
537
543
|
''' run a command on the remote host '''
|
|
538
544
|
|
|
539
545
|
super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable)
|
|
@@ -576,7 +582,7 @@ class Connection(ConnectionBase):
|
|
|
576
582
|
display.debug('Waiting for Privilege Escalation input')
|
|
577
583
|
|
|
578
584
|
chunk = chan.recv(bufsize)
|
|
579
|
-
display.debug("chunk is: %
|
|
585
|
+
display.debug("chunk is: %r" % chunk)
|
|
580
586
|
if not chunk:
|
|
581
587
|
if b'unknown user' in become_output:
|
|
582
588
|
n_become_user = to_native(self.become.get_option('become_user'))
|
|
@@ -606,14 +612,14 @@ class Connection(ConnectionBase):
|
|
|
606
612
|
no_prompt_out += become_output
|
|
607
613
|
no_prompt_err += become_output
|
|
608
614
|
except socket.timeout:
|
|
609
|
-
raise AnsibleError('ssh timed out waiting for privilege escalation.\n' + become_output)
|
|
615
|
+
raise AnsibleError('ssh timed out waiting for privilege escalation.\n' + to_text(become_output))
|
|
610
616
|
|
|
611
617
|
stdout = b''.join(chan.makefile('rb', bufsize))
|
|
612
618
|
stderr = b''.join(chan.makefile_stderr('rb', bufsize))
|
|
613
619
|
|
|
614
620
|
return (chan.recv_exit_status(), no_prompt_out + stdout, no_prompt_out + stderr)
|
|
615
621
|
|
|
616
|
-
def put_file(self, in_path, out_path):
|
|
622
|
+
def put_file(self, in_path: str, out_path: str) -> None:
|
|
617
623
|
''' transfer a file from local to remote '''
|
|
618
624
|
|
|
619
625
|
super(Connection, self).put_file(in_path, out_path)
|
|
@@ -633,7 +639,7 @@ class Connection(ConnectionBase):
|
|
|
633
639
|
except IOError:
|
|
634
640
|
raise AnsibleError("failed to transfer file to %s" % out_path)
|
|
635
641
|
|
|
636
|
-
def _connect_sftp(self):
|
|
642
|
+
def _connect_sftp(self) -> paramiko.sftp_client.SFTPClient:
|
|
637
643
|
|
|
638
644
|
cache_key = "%s__%s__" % (self.get_option('remote_addr'), self.get_option('remote_user'))
|
|
639
645
|
if cache_key in SFTP_CONNECTION_CACHE:
|
|
@@ -642,7 +648,7 @@ class Connection(ConnectionBase):
|
|
|
642
648
|
result = SFTP_CONNECTION_CACHE[cache_key] = self._connect().ssh.open_sftp()
|
|
643
649
|
return result
|
|
644
650
|
|
|
645
|
-
def fetch_file(self, in_path, out_path):
|
|
651
|
+
def fetch_file(self, in_path: str, out_path: str) -> None:
|
|
646
652
|
''' save a remote file to the specified path '''
|
|
647
653
|
|
|
648
654
|
super(Connection, self).fetch_file(in_path, out_path)
|
|
@@ -659,7 +665,7 @@ class Connection(ConnectionBase):
|
|
|
659
665
|
except IOError:
|
|
660
666
|
raise AnsibleError("failed to transfer file from %s" % in_path)
|
|
661
667
|
|
|
662
|
-
def _any_keys_added(self):
|
|
668
|
+
def _any_keys_added(self) -> bool:
|
|
663
669
|
|
|
664
670
|
for hostname, keys in self.ssh._host_keys.items():
|
|
665
671
|
for keytype, key in keys.items():
|
|
@@ -668,14 +674,14 @@ class Connection(ConnectionBase):
|
|
|
668
674
|
return True
|
|
669
675
|
return False
|
|
670
676
|
|
|
671
|
-
def _save_ssh_host_keys(self, filename):
|
|
677
|
+
def _save_ssh_host_keys(self, filename: str) -> None:
|
|
672
678
|
'''
|
|
673
679
|
not using the paramiko save_ssh_host_keys function as we want to add new SSH keys at the bottom so folks
|
|
674
680
|
don't complain about it :)
|
|
675
681
|
'''
|
|
676
682
|
|
|
677
683
|
if not self._any_keys_added():
|
|
678
|
-
return
|
|
684
|
+
return
|
|
679
685
|
|
|
680
686
|
path = os.path.expanduser("~/.ssh")
|
|
681
687
|
makedirs_safe(path)
|
|
@@ -698,13 +704,13 @@ class Connection(ConnectionBase):
|
|
|
698
704
|
if added_this_time:
|
|
699
705
|
f.write("%s %s %s\n" % (hostname, keytype, key.get_base64()))
|
|
700
706
|
|
|
701
|
-
def reset(self):
|
|
707
|
+
def reset(self) -> None:
|
|
702
708
|
if not self._connected:
|
|
703
709
|
return
|
|
704
710
|
self.close()
|
|
705
711
|
self._connect()
|
|
706
712
|
|
|
707
|
-
def close(self):
|
|
713
|
+
def close(self) -> None:
|
|
708
714
|
''' terminate the connection '''
|
|
709
715
|
|
|
710
716
|
cache_key = self._cache_key()
|