ansible-core 2.18.7rc1__py3-none-any.whl → 2.19.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/_internal/__init__.py +53 -0
- ansible/_internal/_ansiballz/__init__.py +0 -0
- ansible/_internal/_ansiballz/_builder.py +101 -0
- ansible/_internal/_ansiballz/_wrapper.py +262 -0
- ansible/_internal/_collection_proxy.py +47 -0
- ansible/_internal/_datatag/__init__.py +0 -0
- ansible/_internal/_datatag/_tags.py +130 -0
- ansible/_internal/_datatag/_utils.py +19 -0
- ansible/_internal/_datatag/_wrappers.py +33 -0
- ansible/_internal/_errors/__init__.py +0 -0
- ansible/_internal/_errors/_alarm_timeout.py +66 -0
- ansible/_internal/_errors/_captured.py +123 -0
- ansible/_internal/_errors/_error_factory.py +89 -0
- ansible/_internal/_errors/_error_utils.py +240 -0
- ansible/_internal/_errors/_handler.py +91 -0
- ansible/_internal/_errors/_task_timeout.py +28 -0
- ansible/_internal/_event_formatting.py +127 -0
- ansible/_internal/_json/__init__.py +214 -0
- ansible/_internal/_json/_legacy_encoder.py +34 -0
- ansible/_internal/_json/_profiles/__init__.py +0 -0
- ansible/_internal/_json/_profiles/_cache_persistence.py +57 -0
- ansible/_internal/_json/_profiles/_inventory_legacy.py +40 -0
- ansible/_internal/_json/_profiles/_legacy.py +189 -0
- ansible/_internal/_locking.py +21 -0
- ansible/_internal/_plugins/__init__.py +0 -0
- ansible/_internal/_plugins/_cache.py +57 -0
- ansible/_internal/_ssh/__init__.py +0 -0
- ansible/_internal/_ssh/_agent_launch.py +91 -0
- ansible/_internal/_ssh/_ssh_agent.py +619 -0
- ansible/_internal/_task.py +78 -0
- ansible/_internal/_templating/__init__.py +12 -0
- ansible/_internal/_templating/_access.py +86 -0
- ansible/_internal/_templating/_chain_templar.py +63 -0
- ansible/_internal/_templating/_datatag.py +95 -0
- ansible/_internal/_templating/_engine.py +592 -0
- ansible/_internal/_templating/_errors.py +28 -0
- ansible/_internal/_templating/_jinja_bits.py +1106 -0
- ansible/_internal/_templating/_jinja_common.py +323 -0
- ansible/_internal/_templating/_jinja_patches.py +44 -0
- ansible/_internal/_templating/_jinja_plugins.py +375 -0
- ansible/_internal/_templating/_lazy_containers.py +633 -0
- ansible/_internal/_templating/_marker_behaviors.py +103 -0
- ansible/_internal/_templating/_template_vars.py +72 -0
- ansible/_internal/_templating/_transform.py +70 -0
- ansible/_internal/_templating/_utils.py +108 -0
- ansible/_internal/_testing.py +26 -0
- ansible/_internal/_wrapt.py +1052 -0
- ansible/_internal/_yaml/__init__.py +0 -0
- ansible/_internal/_yaml/_constructor.py +240 -0
- ansible/_internal/_yaml/_dumper.py +70 -0
- ansible/_internal/_yaml/_errors.py +166 -0
- ansible/_internal/_yaml/_loader.py +66 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/README.md +11 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/action/debug.py +36 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/apply_trust.py +19 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/dump_object.py +27 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/finalize.py +16 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/origin.py +18 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/python_literal_eval.py +24 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/python_literal_eval.yml +33 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/tag_names.py +16 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/true_type.py +17 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/unmask.py +49 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/lookup/config.py +21 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/lookup/config.yml +2 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged.py +15 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged.yml +19 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged_with.py +18 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged_with.yml +19 -0
- ansible/cli/__init__.py +93 -104
- ansible/cli/_ssh_askpass.py +54 -0
- ansible/cli/adhoc.py +20 -10
- ansible/cli/arguments/option_helpers.py +163 -10
- ansible/cli/config.py +43 -68
- ansible/cli/console.py +13 -11
- ansible/cli/doc.py +134 -77
- ansible/cli/galaxy.py +27 -20
- ansible/cli/inventory.py +28 -28
- ansible/cli/playbook.py +4 -12
- ansible/cli/pull.py +6 -3
- ansible/cli/scripts/ansible_connection_cli_stub.py +7 -7
- ansible/cli/vault.py +12 -11
- ansible/compat/__init__.py +2 -2
- ansible/compat/importlib_resources.py +9 -12
- ansible/config/base.yml +218 -133
- ansible/config/manager.py +220 -159
- ansible/constants.py +2 -65
- ansible/errors/__init__.py +350 -256
- ansible/executor/interpreter_discovery.py +28 -149
- ansible/executor/module_common.py +480 -514
- ansible/executor/play_iterator.py +22 -27
- ansible/executor/playbook_executor.py +11 -11
- ansible/executor/powershell/async_watchdog.ps1 +97 -102
- ansible/executor/powershell/async_wrapper.ps1 +204 -153
- ansible/executor/powershell/become_wrapper.ps1 +107 -144
- ansible/executor/powershell/bootstrap_wrapper.ps1 +46 -9
- ansible/executor/powershell/coverage_wrapper.ps1 +91 -135
- ansible/executor/powershell/exec_wrapper.ps1 +675 -196
- ansible/executor/powershell/module_manifest.py +469 -265
- ansible/executor/powershell/module_wrapper.ps1 +195 -186
- ansible/executor/powershell/powershell_expand_user.ps1 +20 -0
- ansible/executor/powershell/powershell_mkdtemp.ps1 +17 -0
- ansible/executor/powershell/psrp_fetch_file.ps1 +41 -0
- ansible/executor/powershell/psrp_put_file.ps1 +122 -0
- ansible/executor/powershell/winrm_fetch_file.ps1 +46 -0
- ansible/executor/powershell/winrm_put_file.ps1 +36 -0
- ansible/executor/process/worker.py +139 -149
- ansible/executor/stats.py +5 -5
- ansible/executor/task_executor.py +270 -297
- ansible/executor/task_queue_manager.py +135 -137
- ansible/executor/task_result.py +182 -79
- ansible/galaxy/__init__.py +2 -2
- ansible/galaxy/api.py +26 -25
- ansible/galaxy/collection/__init__.py +6 -14
- ansible/galaxy/collection/concrete_artifact_manager.py +12 -21
- ansible/galaxy/dependency_resolution/dataclasses.py +14 -4
- ansible/galaxy/dependency_resolution/providers.py +4 -4
- ansible/galaxy/dependency_resolution/reporters.py +81 -0
- ansible/galaxy/role.py +6 -10
- ansible/galaxy/token.py +28 -21
- ansible/inventory/data.py +47 -57
- ansible/inventory/group.py +50 -73
- ansible/inventory/helpers.py +9 -0
- ansible/inventory/host.py +37 -54
- ansible/inventory/manager.py +79 -34
- ansible/keyword_desc.yml +1 -1
- ansible/module_utils/_internal/__init__.py +55 -0
- ansible/module_utils/_internal/_ambient_context.py +58 -0
- ansible/module_utils/_internal/_ansiballz/__init__.py +0 -0
- ansible/module_utils/_internal/_ansiballz/_extensions/__init__.py +0 -0
- ansible/module_utils/_internal/_ansiballz/_extensions/_coverage.py +45 -0
- ansible/module_utils/_internal/_ansiballz/_extensions/_pydevd.py +62 -0
- ansible/module_utils/_internal/_ansiballz/_loader.py +81 -0
- ansible/module_utils/_internal/_ansiballz/_respawn.py +32 -0
- ansible/module_utils/_internal/_ansiballz/_respawn_wrapper.py +23 -0
- ansible/module_utils/_internal/_concurrent/_daemon_threading.py +1 -0
- ansible/module_utils/_internal/_dataclass_validation.py +217 -0
- ansible/module_utils/_internal/_datatag/__init__.py +961 -0
- ansible/module_utils/_internal/_datatag/_tags.py +16 -0
- ansible/module_utils/_internal/_debugging.py +31 -0
- ansible/module_utils/_internal/_deprecator.py +157 -0
- ansible/module_utils/_internal/_errors.py +101 -0
- ansible/module_utils/_internal/_event_utils.py +61 -0
- ansible/module_utils/_internal/_json/__init__.py +63 -0
- ansible/module_utils/_internal/_json/_legacy_encoder.py +26 -0
- ansible/module_utils/_internal/_json/_profiles/__init__.py +428 -0
- ansible/module_utils/_internal/_json/_profiles/_fallback_to_str.py +73 -0
- ansible/module_utils/_internal/_json/_profiles/_module_legacy_c2m.py +33 -0
- ansible/module_utils/_internal/_json/_profiles/_module_legacy_m2c.py +37 -0
- ansible/module_utils/_internal/_json/_profiles/_module_modern_c2m.py +35 -0
- ansible/module_utils/_internal/_json/_profiles/_module_modern_m2c.py +33 -0
- ansible/module_utils/_internal/_json/_profiles/_tagless.py +52 -0
- ansible/module_utils/_internal/_messages.py +130 -0
- ansible/module_utils/_internal/_patches/__init__.py +66 -0
- ansible/module_utils/_internal/_patches/_dataclass_annotation_patch.py +53 -0
- ansible/module_utils/_internal/_patches/_socket_patch.py +34 -0
- ansible/module_utils/_internal/_patches/_sys_intern_patch.py +34 -0
- ansible/module_utils/_internal/_plugin_info.py +38 -0
- ansible/module_utils/_internal/_stack.py +22 -0
- ansible/module_utils/_internal/_testing.py +0 -0
- ansible/module_utils/_internal/_text_utils.py +6 -0
- ansible/module_utils/_internal/_traceback.py +92 -0
- ansible/module_utils/_internal/_validation.py +14 -0
- ansible/module_utils/ansible_release.py +2 -2
- ansible/module_utils/api.py +1 -2
- ansible/module_utils/basic.py +303 -202
- ansible/module_utils/common/_utils.py +24 -28
- ansible/module_utils/common/arg_spec.py +8 -3
- ansible/module_utils/common/collections.py +7 -2
- ansible/module_utils/common/dict_transformations.py +2 -2
- ansible/module_utils/common/file.py +2 -2
- ansible/module_utils/common/json.py +90 -84
- ansible/module_utils/common/locale.py +2 -2
- ansible/module_utils/common/parameters.py +27 -24
- ansible/module_utils/common/process.py +2 -3
- ansible/module_utils/common/respawn.py +11 -33
- ansible/module_utils/common/sentinel.py +66 -0
- ansible/module_utils/common/sys_info.py +8 -8
- ansible/module_utils/common/text/converters.py +16 -37
- ansible/module_utils/common/validation.py +35 -24
- ansible/module_utils/common/warnings.py +143 -25
- ansible/module_utils/common/yaml.py +29 -3
- ansible/module_utils/compat/datetime.py +33 -21
- ansible/module_utils/compat/paramiko.py +21 -10
- ansible/module_utils/compat/typing.py +6 -5
- ansible/module_utils/connection.py +10 -13
- ansible/module_utils/csharp/Ansible.Basic.cs +15 -12
- ansible/module_utils/csharp/Ansible.Become.cs +1 -0
- ansible/module_utils/csharp/Ansible.Privilege.cs +2 -2
- ansible/module_utils/csharp/Ansible._Async.cs +517 -0
- ansible/module_utils/datatag.py +49 -0
- ansible/module_utils/distro/__init__.py +2 -2
- ansible/module_utils/facts/ansible_collector.py +4 -5
- ansible/module_utils/facts/collector.py +13 -14
- ansible/module_utils/facts/compat.py +4 -4
- ansible/module_utils/facts/default_collectors.py +1 -1
- ansible/module_utils/facts/hardware/aix.py +34 -0
- ansible/module_utils/facts/hardware/base.py +2 -2
- ansible/module_utils/facts/hardware/darwin.py +1 -3
- ansible/module_utils/facts/hardware/freebsd.py +2 -2
- ansible/module_utils/facts/hardware/linux.py +5 -5
- ansible/module_utils/facts/namespace.py +1 -1
- ansible/module_utils/facts/network/base.py +1 -1
- ansible/module_utils/facts/network/fc_wwn.py +1 -2
- ansible/module_utils/facts/network/iscsi.py +1 -2
- ansible/module_utils/facts/network/nvme.py +1 -2
- ansible/module_utils/facts/other/facter.py +2 -3
- ansible/module_utils/facts/other/ohai.py +2 -3
- ansible/module_utils/facts/sysctl.py +4 -6
- ansible/module_utils/facts/system/apparmor.py +1 -2
- ansible/module_utils/facts/system/caps.py +3 -3
- ansible/module_utils/facts/system/chroot.py +1 -2
- ansible/module_utils/facts/system/cmdline.py +1 -2
- ansible/module_utils/facts/system/date_time.py +5 -3
- ansible/module_utils/facts/system/distribution.py +27 -13
- ansible/module_utils/facts/system/dns.py +1 -1
- ansible/module_utils/facts/system/env.py +1 -2
- ansible/module_utils/facts/system/fips.py +7 -20
- ansible/module_utils/facts/system/loadavg.py +1 -2
- ansible/module_utils/facts/system/local.py +2 -3
- ansible/module_utils/facts/system/lsb.py +1 -2
- ansible/module_utils/facts/system/pkg_mgr.py +1 -2
- ansible/module_utils/facts/system/platform.py +1 -2
- ansible/module_utils/facts/system/python.py +1 -2
- ansible/module_utils/facts/system/selinux.py +1 -1
- ansible/module_utils/facts/system/service_mgr.py +1 -2
- ansible/module_utils/facts/system/ssh_pub_keys.py +1 -1
- ansible/module_utils/facts/system/systemd.py +1 -1
- ansible/module_utils/facts/system/user.py +1 -2
- ansible/module_utils/facts/utils.py +3 -3
- ansible/module_utils/facts/virtual/base.py +1 -1
- ansible/module_utils/facts/virtual/linux.py +3 -3
- ansible/module_utils/facts/virtual/sunos.py +3 -15
- ansible/module_utils/facts/virtual/sysctl.py +3 -16
- ansible/module_utils/json_utils.py +2 -2
- ansible/module_utils/parsing/convert_bool.py +7 -1
- ansible/module_utils/powershell/Ansible.ModuleUtils.AddType.psm1 +1 -1
- ansible/module_utils/powershell/Ansible.ModuleUtils.CamelConversion.psm1 +1 -1
- ansible/module_utils/powershell/Ansible.ModuleUtils.CommandUtil.psm1 +1 -1
- ansible/module_utils/powershell/Ansible.ModuleUtils.WebRequest.psm1 +1 -1
- ansible/module_utils/service.py +21 -31
- ansible/module_utils/splitter.py +7 -7
- ansible/module_utils/testing.py +31 -0
- ansible/module_utils/urls.py +64 -35
- ansible/modules/add_host.py +4 -4
- ansible/modules/apt.py +69 -49
- ansible/modules/apt_key.py +19 -12
- ansible/modules/apt_repository.py +32 -51
- ansible/modules/assemble.py +16 -14
- ansible/modules/assert.py +4 -4
- ansible/modules/async_status.py +24 -24
- ansible/modules/async_wrapper.py +20 -25
- ansible/modules/blockinfile.py +6 -7
- ansible/modules/command.py +13 -20
- ansible/modules/copy.py +60 -147
- ansible/modules/cron.py +24 -21
- ansible/modules/deb822_repository.py +8 -9
- ansible/modules/debconf.py +5 -5
- ansible/modules/debug.py +4 -4
- ansible/modules/dnf.py +8 -8
- ansible/modules/dnf5.py +39 -13
- ansible/modules/dpkg_selections.py +4 -4
- ansible/modules/expect.py +13 -15
- ansible/modules/fail.py +4 -4
- ansible/modules/fetch.py +4 -4
- ansible/modules/file.py +184 -144
- ansible/modules/find.py +22 -20
- ansible/modules/gather_facts.py +3 -3
- ansible/modules/get_url.py +77 -54
- ansible/modules/getent.py +7 -9
- ansible/modules/git.py +38 -38
- ansible/modules/group.py +6 -6
- ansible/modules/group_by.py +4 -4
- ansible/modules/hostname.py +15 -32
- ansible/modules/import_playbook.py +6 -6
- ansible/modules/import_role.py +6 -6
- ansible/modules/import_tasks.py +6 -6
- ansible/modules/include_role.py +6 -6
- ansible/modules/include_tasks.py +6 -6
- ansible/modules/include_vars.py +6 -6
- ansible/modules/iptables.py +86 -73
- ansible/modules/known_hosts.py +22 -24
- ansible/modules/lineinfile.py +5 -5
- ansible/modules/meta.py +4 -4
- ansible/modules/mount_facts.py +2 -2
- ansible/modules/package.py +10 -4
- ansible/modules/package_facts.py +22 -10
- ansible/modules/pause.py +6 -6
- ansible/modules/ping.py +6 -6
- ansible/modules/pip.py +21 -26
- ansible/modules/raw.py +6 -6
- ansible/modules/reboot.py +6 -6
- ansible/modules/replace.py +10 -14
- ansible/modules/rpm_key.py +7 -8
- ansible/modules/script.py +4 -4
- ansible/modules/service.py +10 -17
- ansible/modules/service_facts.py +87 -10
- ansible/modules/set_fact.py +5 -5
- ansible/modules/set_stats.py +4 -4
- ansible/modules/setup.py +2 -2
- ansible/modules/shell.py +6 -6
- ansible/modules/slurp.py +16 -19
- ansible/modules/stat.py +15 -31
- ansible/modules/subversion.py +15 -15
- ansible/modules/systemd.py +7 -7
- ansible/modules/systemd_service.py +7 -7
- ansible/modules/sysvinit.py +9 -9
- ansible/modules/tempfile.py +5 -6
- ansible/modules/template.py +6 -6
- ansible/modules/unarchive.py +38 -17
- ansible/modules/uri.py +33 -26
- ansible/modules/user.py +45 -32
- ansible/modules/validate_argument_spec.py +10 -7
- ansible/modules/wait_for.py +70 -60
- ansible/modules/wait_for_connection.py +6 -6
- ansible/modules/yum_repository.py +10 -9
- ansible/parsing/ajson.py +17 -37
- ansible/parsing/dataloader.py +99 -54
- ansible/parsing/mod_args.py +62 -60
- ansible/parsing/plugin_docs.py +21 -86
- ansible/parsing/quoting.py +1 -1
- ansible/parsing/splitter.py +27 -12
- ansible/parsing/utils/addresses.py +24 -24
- ansible/parsing/utils/jsonify.py +5 -1
- ansible/parsing/utils/yaml.py +32 -61
- ansible/parsing/vault/__init__.py +327 -99
- ansible/parsing/yaml/__init__.py +0 -18
- ansible/parsing/yaml/dumper.py +6 -120
- ansible/parsing/yaml/loader.py +6 -39
- ansible/parsing/yaml/objects.py +43 -335
- ansible/playbook/__init__.py +1 -1
- ansible/playbook/attribute.py +8 -3
- ansible/playbook/base.py +187 -134
- ansible/playbook/block.py +26 -24
- ansible/playbook/collectionsearch.py +1 -15
- ansible/playbook/conditional.py +3 -77
- ansible/playbook/handler.py +8 -2
- ansible/playbook/helpers.py +41 -53
- ansible/playbook/included_file.py +32 -26
- ansible/playbook/loop_control.py +2 -2
- ansible/playbook/play.py +85 -44
- ansible/playbook/play_context.py +14 -17
- ansible/playbook/playbook_include.py +27 -62
- ansible/playbook/role/__init__.py +64 -49
- ansible/playbook/role/definition.py +15 -17
- ansible/playbook/role/include.py +2 -4
- ansible/playbook/role/metadata.py +10 -11
- ansible/playbook/role_include.py +3 -3
- ansible/playbook/taggable.py +28 -12
- ansible/playbook/task.py +192 -121
- ansible/playbook/task_include.py +5 -5
- ansible/plugins/__init__.py +58 -26
- ansible/plugins/action/__init__.py +188 -186
- ansible/plugins/action/add_host.py +2 -2
- ansible/plugins/action/assemble.py +11 -18
- ansible/plugins/action/assert.py +55 -67
- ansible/plugins/action/async_status.py +7 -2
- ansible/plugins/action/copy.py +14 -17
- ansible/plugins/action/debug.py +37 -31
- ansible/plugins/action/dnf.py +3 -4
- ansible/plugins/action/fail.py +1 -1
- ansible/plugins/action/fetch.py +7 -8
- ansible/plugins/action/gather_facts.py +13 -14
- ansible/plugins/action/group_by.py +1 -1
- ansible/plugins/action/include_vars.py +10 -11
- ansible/plugins/action/package.py +8 -14
- ansible/plugins/action/pause.py +2 -2
- ansible/plugins/action/script.py +27 -38
- ansible/plugins/action/service.py +9 -18
- ansible/plugins/action/set_fact.py +3 -12
- ansible/plugins/action/set_stats.py +3 -8
- ansible/plugins/action/template.py +47 -67
- ansible/plugins/action/unarchive.py +6 -16
- ansible/plugins/action/uri.py +9 -20
- ansible/plugins/action/validate_argument_spec.py +5 -5
- ansible/plugins/action/wait_for_connection.py +1 -1
- ansible/plugins/become/__init__.py +31 -8
- ansible/plugins/become/runas.py +71 -0
- ansible/plugins/become/su.py +13 -8
- ansible/plugins/become/sudo.py +19 -0
- ansible/plugins/cache/__init__.py +52 -63
- ansible/plugins/cache/base.py +8 -0
- ansible/plugins/cache/jsonfile.py +10 -16
- ansible/plugins/cache/memory.py +6 -12
- ansible/plugins/callback/__init__.py +294 -201
- ansible/plugins/callback/default.py +99 -95
- ansible/plugins/callback/junit.py +44 -43
- ansible/plugins/callback/minimal.py +28 -25
- ansible/plugins/callback/oneline.py +34 -21
- ansible/plugins/callback/tree.py +27 -16
- ansible/plugins/connection/__init__.py +47 -34
- ansible/plugins/connection/local.py +156 -60
- ansible/plugins/connection/paramiko_ssh.py +34 -24
- ansible/plugins/connection/psrp.py +76 -165
- ansible/plugins/connection/ssh.py +326 -86
- ansible/plugins/connection/winrm.py +62 -141
- ansible/plugins/doc_fragments/action_common_attributes.py +14 -14
- ansible/plugins/doc_fragments/action_core.py +6 -6
- ansible/plugins/doc_fragments/backup.py +2 -2
- ansible/plugins/doc_fragments/checksum_common.py +27 -0
- ansible/plugins/doc_fragments/constructed.py +8 -4
- ansible/plugins/doc_fragments/decrypt.py +2 -2
- ansible/plugins/doc_fragments/default_callback.py +2 -2
- ansible/plugins/doc_fragments/files.py +2 -2
- ansible/plugins/doc_fragments/inventory_cache.py +2 -2
- ansible/plugins/doc_fragments/result_format_callback.py +2 -2
- ansible/plugins/doc_fragments/return_common.py +2 -2
- ansible/plugins/doc_fragments/template_common.py +4 -4
- ansible/plugins/doc_fragments/url.py +17 -1
- ansible/plugins/doc_fragments/url_windows.py +2 -2
- ansible/plugins/doc_fragments/validate.py +2 -2
- ansible/plugins/doc_fragments/vars_plugin_staging.py +2 -2
- ansible/plugins/filter/__init__.py +6 -2
- ansible/plugins/filter/b64decode.yml +22 -0
- ansible/plugins/filter/b64encode.yml +22 -0
- ansible/plugins/filter/bool.yml +11 -4
- ansible/plugins/filter/core.py +245 -120
- ansible/plugins/filter/encryption.py +42 -34
- ansible/plugins/filter/flatten.yml +3 -2
- ansible/plugins/filter/human_to_bytes.yml +1 -1
- ansible/plugins/filter/mathstuff.py +30 -37
- ansible/plugins/filter/password_hash.yml +8 -0
- ansible/plugins/filter/pow.yml +1 -1
- ansible/plugins/filter/regex_search.yml +1 -4
- ansible/plugins/filter/root.yml +1 -1
- ansible/plugins/filter/split.yml +1 -1
- ansible/plugins/filter/strftime.yml +3 -3
- ansible/plugins/filter/to_nice_yaml.yml +0 -4
- ansible/plugins/filter/to_uuid.yml +1 -1
- ansible/plugins/filter/to_yaml.yml +0 -4
- ansible/plugins/filter/unvault.yml +1 -1
- ansible/plugins/filter/urls.py +1 -1
- ansible/plugins/filter/urlsplit.py +8 -9
- ansible/plugins/filter/vault.yml +14 -9
- ansible/plugins/filter/win_basename.yml +6 -1
- ansible/plugins/filter/win_dirname.yml +5 -0
- ansible/plugins/inventory/__init__.py +107 -86
- ansible/plugins/inventory/advanced_host_list.py +7 -5
- ansible/plugins/inventory/auto.py +11 -4
- ansible/plugins/inventory/constructed.py +21 -24
- ansible/plugins/inventory/generator.py +16 -11
- ansible/plugins/inventory/host_list.py +7 -5
- ansible/plugins/inventory/ini.py +78 -44
- ansible/plugins/inventory/script.py +190 -120
- ansible/plugins/inventory/toml.py +16 -126
- ansible/plugins/inventory/yaml.py +10 -8
- ansible/plugins/list.py +72 -19
- ansible/plugins/loader.py +383 -198
- ansible/plugins/lookup/__init__.py +21 -4
- ansible/plugins/lookup/config.py +21 -35
- ansible/plugins/lookup/csvfile.py +19 -73
- ansible/plugins/lookup/dict.py +1 -6
- ansible/plugins/lookup/env.py +12 -9
- ansible/plugins/lookup/file.py +5 -8
- ansible/plugins/lookup/first_found.py +87 -55
- ansible/plugins/lookup/indexed_items.py +1 -10
- ansible/plugins/lookup/ini.py +14 -13
- ansible/plugins/lookup/items.py +1 -1
- ansible/plugins/lookup/lines.py +8 -1
- ansible/plugins/lookup/list.py +1 -1
- ansible/plugins/lookup/nested.py +2 -18
- ansible/plugins/lookup/password.py +5 -5
- ansible/plugins/lookup/pipe.py +5 -7
- ansible/plugins/lookup/sequence.py +18 -8
- ansible/plugins/lookup/subelements.py +1 -4
- ansible/plugins/lookup/template.py +47 -36
- ansible/plugins/lookup/together.py +0 -12
- ansible/plugins/lookup/unvault.py +1 -5
- ansible/plugins/lookup/url.py +4 -10
- ansible/plugins/lookup/vars.py +16 -24
- ansible/plugins/shell/__init__.py +58 -4
- ansible/plugins/shell/cmd.py +2 -2
- ansible/plugins/shell/powershell.py +106 -31
- ansible/plugins/shell/sh.py +13 -7
- ansible/plugins/strategy/__init__.py +168 -193
- ansible/plugins/strategy/debug.py +2 -2
- ansible/plugins/strategy/free.py +16 -31
- ansible/plugins/strategy/host_pinned.py +2 -2
- ansible/plugins/strategy/linear.py +41 -41
- ansible/plugins/terminal/__init__.py +4 -4
- ansible/plugins/test/__init__.py +7 -2
- ansible/plugins/test/core.py +75 -35
- ansible/plugins/test/files.py +1 -1
- ansible/plugins/test/finished.yml +1 -1
- ansible/plugins/test/mathstuff.py +3 -3
- ansible/plugins/test/uri.py +5 -8
- ansible/plugins/vars/host_group_vars.py +7 -14
- ansible/release.py +2 -2
- ansible/template/__init__.py +353 -943
- ansible/utils/__init__.py +0 -18
- ansible/utils/collection_loader/__init__.py +54 -5
- ansible/utils/collection_loader/_collection_config.py +5 -6
- ansible/utils/collection_loader/_collection_finder.py +82 -96
- ansible/utils/collection_loader/_collection_meta.py +15 -8
- ansible/utils/display.py +485 -73
- ansible/utils/encrypt.py +27 -19
- ansible/utils/fqcn.py +2 -2
- ansible/utils/galaxy.py +2 -2
- ansible/utils/hashing.py +8 -10
- ansible/utils/helpers.py +2 -2
- ansible/utils/listify.py +10 -8
- ansible/utils/lock.py +2 -2
- ansible/utils/path.py +10 -12
- ansible/utils/plugin_docs.py +16 -14
- ansible/utils/py3compat.py +2 -7
- ansible/utils/sentinel.py +4 -62
- ansible/utils/singleton.py +2 -0
- ansible/utils/ssh_functions.py +6 -2
- ansible/utils/unsafe_proxy.py +23 -332
- ansible/utils/vars.py +55 -8
- ansible/utils/version.py +2 -2
- ansible/vars/clean.py +5 -5
- ansible/vars/hostvars.py +60 -90
- ansible/vars/manager.py +220 -285
- ansible/vars/plugins.py +4 -4
- ansible/vars/reserved.py +13 -12
- {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/METADATA +4 -3
- ansible_core-2.19.0.dist-info/RECORD +1097 -0
- ansible_core-2.19.0.dist-info/licenses/licenses/BSD-3-Clause.txt +28 -0
- ansible_test/_data/completion/docker.txt +7 -7
- ansible_test/_data/completion/remote.txt +6 -6
- ansible_test/_data/completion/windows.txt +1 -0
- ansible_test/_data/requirements/ansible.txt +2 -2
- ansible_test/_data/requirements/sanity.ansible-doc.txt +3 -3
- ansible_test/_data/requirements/sanity.changelog.txt +2 -2
- ansible_test/_data/requirements/sanity.import.plugin.txt +2 -2
- ansible_test/_data/requirements/sanity.pep8.txt +1 -1
- ansible_test/_data/requirements/sanity.pylint.txt +5 -5
- ansible_test/_data/requirements/sanity.validate-modules.txt +2 -2
- ansible_test/_data/requirements/sanity.yamllint.txt +1 -1
- ansible_test/_data/requirements/units.txt +1 -0
- ansible_test/_internal/__init__.py +6 -0
- ansible_test/_internal/ansible_util.py +3 -1
- ansible_test/_internal/become.py +1 -0
- ansible_test/_internal/bootstrap.py +1 -0
- ansible_test/_internal/cache.py +1 -0
- ansible_test/_internal/cgroup.py +1 -0
- ansible_test/_internal/ci/__init__.py +1 -0
- ansible_test/_internal/ci/azp.py +1 -0
- ansible_test/_internal/ci/local.py +1 -0
- ansible_test/_internal/classification/__init__.py +1 -0
- ansible_test/_internal/classification/common.py +1 -0
- ansible_test/_internal/classification/csharp.py +1 -0
- ansible_test/_internal/classification/powershell.py +1 -0
- ansible_test/_internal/classification/python.py +1 -0
- ansible_test/_internal/cli/__init__.py +1 -0
- ansible_test/_internal/cli/actions.py +1 -0
- ansible_test/_internal/cli/argparsing/__init__.py +1 -0
- ansible_test/_internal/cli/argparsing/actions.py +1 -0
- ansible_test/_internal/cli/argparsing/argcompletion.py +1 -0
- ansible_test/_internal/cli/argparsing/parsers.py +1 -0
- ansible_test/_internal/cli/commands/__init__.py +11 -5
- ansible_test/_internal/cli/commands/coverage/__init__.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/__init__.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/__init__.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/combine.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/expand.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/filter.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/generate.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/missing.py +1 -0
- ansible_test/_internal/cli/commands/coverage/combine.py +1 -0
- ansible_test/_internal/cli/commands/coverage/erase.py +1 -0
- ansible_test/_internal/cli/commands/coverage/html.py +1 -0
- ansible_test/_internal/cli/commands/coverage/report.py +1 -0
- ansible_test/_internal/cli/commands/coverage/xml.py +1 -0
- ansible_test/_internal/cli/commands/env.py +1 -0
- ansible_test/_internal/cli/commands/integration/__init__.py +1 -0
- ansible_test/_internal/cli/commands/integration/network.py +1 -0
- ansible_test/_internal/cli/commands/integration/posix.py +1 -0
- ansible_test/_internal/cli/commands/integration/windows.py +1 -0
- ansible_test/_internal/cli/commands/sanity.py +9 -0
- ansible_test/_internal/cli/commands/shell.py +1 -0
- ansible_test/_internal/cli/commands/units.py +1 -0
- ansible_test/_internal/cli/compat.py +1 -0
- ansible_test/_internal/cli/completers.py +1 -0
- ansible_test/_internal/cli/converters.py +1 -0
- ansible_test/_internal/cli/environments.py +52 -5
- ansible_test/_internal/cli/epilog.py +1 -0
- ansible_test/_internal/cli/parsers/__init__.py +1 -0
- ansible_test/_internal/cli/parsers/base_argument_parsers.py +1 -0
- ansible_test/_internal/cli/parsers/helpers.py +1 -0
- ansible_test/_internal/cli/parsers/host_config_parsers.py +1 -0
- ansible_test/_internal/cli/parsers/key_value_parsers.py +1 -0
- ansible_test/_internal/cli/parsers/value_parsers.py +1 -0
- ansible_test/_internal/commands/__init__.py +1 -0
- ansible_test/_internal/commands/coverage/__init__.py +3 -2
- ansible_test/_internal/commands/coverage/analyze/__init__.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/__init__.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/combine.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/expand.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/filter.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/generate.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/missing.py +1 -0
- ansible_test/_internal/commands/coverage/combine.py +2 -1
- ansible_test/_internal/commands/coverage/erase.py +1 -0
- ansible_test/_internal/commands/coverage/html.py +1 -0
- ansible_test/_internal/commands/coverage/report.py +1 -0
- ansible_test/_internal/commands/coverage/xml.py +1 -0
- ansible_test/_internal/commands/env/__init__.py +2 -0
- ansible_test/_internal/commands/integration/__init__.py +22 -5
- ansible_test/_internal/commands/integration/cloud/__init__.py +1 -0
- ansible_test/_internal/commands/integration/cloud/acme.py +2 -1
- ansible_test/_internal/commands/integration/cloud/aws.py +1 -0
- ansible_test/_internal/commands/integration/cloud/azure.py +1 -0
- ansible_test/_internal/commands/integration/cloud/cs.py +1 -0
- ansible_test/_internal/commands/integration/cloud/digitalocean.py +1 -0
- ansible_test/_internal/commands/integration/cloud/galaxy.py +3 -2
- ansible_test/_internal/commands/integration/cloud/hcloud.py +1 -0
- ansible_test/_internal/commands/integration/cloud/httptester.py +3 -2
- ansible_test/_internal/commands/integration/cloud/nios.py +2 -1
- ansible_test/_internal/commands/integration/cloud/opennebula.py +1 -0
- ansible_test/_internal/commands/integration/cloud/openshift.py +1 -0
- ansible_test/_internal/commands/integration/cloud/scaleway.py +1 -0
- ansible_test/_internal/commands/integration/cloud/vcenter.py +1 -0
- ansible_test/_internal/commands/integration/cloud/vultr.py +1 -0
- ansible_test/_internal/commands/integration/coverage.py +8 -2
- ansible_test/_internal/commands/integration/filters.py +1 -0
- ansible_test/_internal/commands/integration/network.py +1 -0
- ansible_test/_internal/commands/integration/posix.py +1 -0
- ansible_test/_internal/commands/integration/windows.py +1 -0
- ansible_test/_internal/commands/sanity/__init__.py +19 -2
- ansible_test/_internal/commands/sanity/ansible_doc.py +1 -0
- ansible_test/_internal/commands/sanity/bin_symlinks.py +1 -0
- ansible_test/_internal/commands/sanity/compile.py +1 -0
- ansible_test/_internal/commands/sanity/ignores.py +1 -0
- ansible_test/_internal/commands/sanity/import.py +1 -0
- ansible_test/_internal/commands/sanity/integration_aliases.py +12 -0
- ansible_test/_internal/commands/sanity/pep8.py +1 -0
- ansible_test/_internal/commands/sanity/pslint.py +1 -0
- ansible_test/_internal/commands/sanity/pylint.py +25 -26
- ansible_test/_internal/commands/sanity/shellcheck.py +1 -0
- ansible_test/_internal/commands/sanity/validate_modules.py +1 -0
- ansible_test/_internal/commands/sanity/yamllint.py +1 -0
- ansible_test/_internal/commands/shell/__init__.py +44 -4
- ansible_test/_internal/commands/units/__init__.py +5 -1
- ansible_test/_internal/compat/__init__.py +1 -0
- ansible_test/_internal/compat/packaging.py +1 -0
- ansible_test/_internal/compat/yaml.py +1 -0
- ansible_test/_internal/completion.py +1 -0
- ansible_test/_internal/config.py +23 -13
- ansible_test/_internal/connections.py +1 -0
- ansible_test/_internal/constants.py +1 -0
- ansible_test/_internal/containers.py +1 -0
- ansible_test/_internal/content_config.py +1 -0
- ansible_test/_internal/core_ci.py +1 -0
- ansible_test/_internal/coverage_util.py +11 -10
- ansible_test/_internal/data.py +1 -0
- ansible_test/_internal/debugging.py +166 -0
- ansible_test/_internal/delegation.py +22 -13
- ansible_test/_internal/dev/__init__.py +1 -0
- ansible_test/_internal/dev/container_probe.py +1 -0
- ansible_test/_internal/diff.py +3 -2
- ansible_test/_internal/docker_util.py +2 -1
- ansible_test/_internal/encoding.py +1 -0
- ansible_test/_internal/executor.py +1 -0
- ansible_test/_internal/git.py +1 -0
- ansible_test/_internal/host_configs.py +1 -0
- ansible_test/_internal/host_profiles.py +260 -16
- ansible_test/_internal/http.py +1 -0
- ansible_test/_internal/init.py +1 -0
- ansible_test/_internal/inventory.py +39 -3
- ansible_test/_internal/io.py +1 -0
- ansible_test/_internal/metadata.py +95 -4
- ansible_test/_internal/payload.py +1 -0
- ansible_test/_internal/processes.py +80 -0
- ansible_test/_internal/provider/__init__.py +1 -0
- ansible_test/_internal/provider/layout/__init__.py +1 -0
- ansible_test/_internal/provider/layout/ansible.py +1 -0
- ansible_test/_internal/provider/layout/collection.py +1 -0
- ansible_test/_internal/provider/layout/unsupported.py +1 -0
- ansible_test/_internal/provider/source/__init__.py +1 -0
- ansible_test/_internal/provider/source/git.py +1 -0
- ansible_test/_internal/provider/source/installed.py +1 -0
- ansible_test/_internal/provider/source/unsupported.py +1 -0
- ansible_test/_internal/provider/source/unversioned.py +1 -0
- ansible_test/_internal/provisioning.py +11 -4
- ansible_test/_internal/pypi_proxy.py +6 -5
- ansible_test/_internal/python_requirements.py +28 -0
- ansible_test/_internal/ssh.py +2 -5
- ansible_test/_internal/target.py +9 -0
- ansible_test/_internal/test.py +3 -2
- ansible_test/_internal/thread.py +3 -1
- ansible_test/_internal/timeout.py +2 -1
- ansible_test/_internal/util.py +41 -12
- ansible_test/_internal/util_common.py +18 -5
- ansible_test/_internal/venv.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/action-plugin-docs.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/changelog/sphinx.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/changelog.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/empty-init.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/line-endings.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-assert.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-get-exception.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-illegal-filenames.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-smart-quotes.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/replace-urlopen.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/runtime-metadata.py +28 -1
- ansible_test/_util/controller/sanity/code-smell/shebang.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/symlinks.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/use-argspec-type-path.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/use-compat-six.py +1 -0
- ansible_test/_util/controller/sanity/integration-aliases/yaml_to_json.py +2 -1
- ansible_test/_util/controller/sanity/pep8/current-ignore.txt +4 -0
- ansible_test/_util/controller/sanity/pylint/config/ansible-test-target.cfg +8 -5
- ansible_test/_util/controller/sanity/pylint/config/ansible-test.cfg +8 -5
- ansible_test/_util/controller/sanity/pylint/config/code-smell.cfg +8 -5
- ansible_test/_util/controller/sanity/pylint/config/collection.cfg +4 -5
- ansible_test/_util/controller/sanity/pylint/config/default.cfg +8 -7
- ansible_test/_util/controller/sanity/pylint/plugins/deprecated_calls.py +541 -0
- ansible_test/_util/controller/sanity/pylint/plugins/deprecated_comment.py +137 -0
- ansible_test/_util/controller/sanity/pylint/plugins/hide_unraisable.py +1 -0
- ansible_test/_util/controller/sanity/pylint/plugins/string_format.py +1 -8
- ansible_test/_util/controller/sanity/pylint/plugins/unwanted.py +1 -8
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py +55 -28
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/module_args.py +12 -5
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/schema.py +13 -2
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/utils.py +1 -0
- ansible_test/_util/controller/sanity/yamllint/yamllinter.py +35 -17
- ansible_test/_util/controller/tools/collection_detail.py +1 -0
- ansible_test/_util/controller/tools/yaml_to_json.py +2 -1
- ansible_test/_util/target/injector/python.py +8 -0
- ansible_test/_util/target/pytest/plugins/ansible_forked.py +6 -1
- ansible_test/_util/target/pytest/plugins/ansible_pytest_collections.py +2 -1
- ansible_test/_util/target/pytest/plugins/ansible_pytest_coverage.py +1 -0
- ansible_test/_util/target/sanity/compile/compile.py +1 -0
- ansible_test/_util/target/sanity/import/importer.py +15 -16
- ansible_test/_util/target/setup/bootstrap.sh +9 -20
- ansible_test/_util/target/setup/probe_cgroups.py +1 -0
- ansible_test/_util/target/setup/quiet_pip.py +1 -0
- ansible_test/_util/target/setup/requirements.py +38 -36
- ansible_test/_util/target/tools/virtualenvcheck.py +2 -1
- ansible_test/_util/target/tools/yamlcheck.py +2 -1
- ansible/compat/selectors.py +0 -32
- ansible/errors/yaml_strings.py +0 -138
- ansible/executor/action_write_locks.py +0 -44
- ansible/executor/discovery/python_target.py +0 -47
- ansible/executor/powershell/module_powershell_wrapper.ps1 +0 -86
- ansible/executor/powershell/module_script_wrapper.ps1 +0 -22
- ansible/module_utils/compat/importlib.py +0 -26
- ansible/module_utils/compat/selectors.py +0 -32
- ansible/module_utils/pycompat24.py +0 -73
- ansible/parsing/yaml/constructor.py +0 -178
- ansible/template/native_helpers.py +0 -251
- ansible/template/template.py +0 -43
- ansible/template/vars.py +0 -77
- ansible/utils/native_jinja.py +0 -11
- ansible/vars/fact_cache.py +0 -71
- ansible_core-2.18.7rc1.dist-info/RECORD +0 -992
- ansible_test/_util/controller/sanity/pylint/plugins/deprecated.py +0 -411
- {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/WHEEL +0 -0
- {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/entry_points.txt +0 -0
- {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/COPYING +0 -0
- {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/Apache-License.txt +0 -0
- {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/MIT-license.txt +0 -0
- {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/PSF-license.txt +0 -0
- {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/simplified_bsd.txt +0 -0
- {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/top_level.txt +0 -0
|
@@ -4,30 +4,49 @@
|
|
|
4
4
|
|
|
5
5
|
from __future__ import annotations
|
|
6
6
|
|
|
7
|
-
DOCUMENTATION =
|
|
7
|
+
DOCUMENTATION = """
|
|
8
8
|
name: local
|
|
9
9
|
short_description: execute on controller
|
|
10
10
|
description:
|
|
11
11
|
- This connection plugin allows ansible to execute tasks on the Ansible 'controller' instead of on a remote host.
|
|
12
12
|
author: ansible (@core)
|
|
13
13
|
version_added: historical
|
|
14
|
+
options:
|
|
15
|
+
become_success_timeout:
|
|
16
|
+
version_added: '2.19'
|
|
17
|
+
type: int
|
|
18
|
+
default: 10
|
|
19
|
+
description:
|
|
20
|
+
- Number of seconds to wait for become to succeed when enabled.
|
|
21
|
+
- The default will be used if the configured value is less than 1.
|
|
22
|
+
vars:
|
|
23
|
+
- name: ansible_local_become_success_timeout
|
|
24
|
+
become_strip_preamble:
|
|
25
|
+
version_added: '2.19'
|
|
26
|
+
type: bool
|
|
27
|
+
default: true
|
|
28
|
+
description:
|
|
29
|
+
- Strip internal become output preceding command execution. Disable for additional diagnostics.
|
|
30
|
+
vars:
|
|
31
|
+
- name: ansible_local_become_strip_preamble
|
|
14
32
|
extends_documentation_fragment:
|
|
15
33
|
- connection_pipelining
|
|
16
34
|
notes:
|
|
17
35
|
- The remote user is ignored, the user with which the ansible CLI was executed is used instead.
|
|
18
|
-
|
|
36
|
+
"""
|
|
19
37
|
|
|
20
|
-
import
|
|
38
|
+
import functools
|
|
21
39
|
import getpass
|
|
22
40
|
import os
|
|
23
41
|
import pty
|
|
24
42
|
import selectors
|
|
25
43
|
import shutil
|
|
26
44
|
import subprocess
|
|
45
|
+
import time
|
|
27
46
|
import typing as t
|
|
28
47
|
|
|
29
48
|
import ansible.constants as C
|
|
30
|
-
from ansible.errors import AnsibleError, AnsibleFileNotFound
|
|
49
|
+
from ansible.errors import AnsibleError, AnsibleFileNotFound, AnsibleConnectionFailure
|
|
31
50
|
from ansible.module_utils.six import text_type, binary_type
|
|
32
51
|
from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text
|
|
33
52
|
from ansible.plugins.connection import ConnectionBase
|
|
@@ -38,7 +57,7 @@ display = Display()
|
|
|
38
57
|
|
|
39
58
|
|
|
40
59
|
class Connection(ConnectionBase):
|
|
41
|
-
|
|
60
|
+
""" Local based connections """
|
|
42
61
|
|
|
43
62
|
transport = 'local'
|
|
44
63
|
has_pipelining = True
|
|
@@ -54,7 +73,7 @@ class Connection(ConnectionBase):
|
|
|
54
73
|
self.default_user = ""
|
|
55
74
|
|
|
56
75
|
def _connect(self) -> Connection:
|
|
57
|
-
|
|
76
|
+
""" connect to the local host; nothing to do here """
|
|
58
77
|
|
|
59
78
|
# Because we haven't made any remote connection we're running as
|
|
60
79
|
# the local user, rather than as whatever is configured in remote_user.
|
|
@@ -66,7 +85,7 @@ class Connection(ConnectionBase):
|
|
|
66
85
|
return self
|
|
67
86
|
|
|
68
87
|
def exec_command(self, cmd: str, in_data: bytes | None = None, sudoable: bool = True) -> tuple[int, bytes, bytes]:
|
|
69
|
-
|
|
88
|
+
""" run a command on the local host """
|
|
70
89
|
|
|
71
90
|
super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable)
|
|
72
91
|
|
|
@@ -82,11 +101,11 @@ class Connection(ConnectionBase):
|
|
|
82
101
|
display.debug("opening command with Popen()")
|
|
83
102
|
|
|
84
103
|
if isinstance(cmd, (text_type, binary_type)):
|
|
85
|
-
cmd =
|
|
104
|
+
cmd = to_text(cmd)
|
|
86
105
|
else:
|
|
87
|
-
cmd = map(
|
|
106
|
+
cmd = map(to_text, cmd)
|
|
88
107
|
|
|
89
|
-
|
|
108
|
+
pty_primary = None
|
|
90
109
|
stdin = subprocess.PIPE
|
|
91
110
|
if sudoable and self.become and self.become.expect_prompt() and not self.get_option('pipelining'):
|
|
92
111
|
# Create a pty if sudoable for privilege escalation that needs it.
|
|
@@ -94,9 +113,9 @@ class Connection(ConnectionBase):
|
|
|
94
113
|
# cause the command to fail in certain situations where we are escalating
|
|
95
114
|
# privileges or the command otherwise needs a pty.
|
|
96
115
|
try:
|
|
97
|
-
|
|
98
|
-
except
|
|
99
|
-
display.debug("Unable to open pty:
|
|
116
|
+
pty_primary, stdin = pty.openpty()
|
|
117
|
+
except OSError as ex:
|
|
118
|
+
display.debug(f"Unable to open pty: {ex}")
|
|
100
119
|
|
|
101
120
|
p = subprocess.Popen(
|
|
102
121
|
cmd,
|
|
@@ -108,63 +127,137 @@ class Connection(ConnectionBase):
|
|
|
108
127
|
stderr=subprocess.PIPE,
|
|
109
128
|
)
|
|
110
129
|
|
|
111
|
-
# if we created a
|
|
112
|
-
if
|
|
130
|
+
# if we created a pty, we can close the other half of the pty now, otherwise primary is stdin
|
|
131
|
+
if pty_primary is not None:
|
|
113
132
|
os.close(stdin)
|
|
114
133
|
|
|
115
134
|
display.debug("done running command with Popen()")
|
|
116
135
|
|
|
117
|
-
|
|
118
|
-
fcntl.fcntl(p.stdout, fcntl.F_SETFL, fcntl.fcntl(p.stdout, fcntl.F_GETFL) | os.O_NONBLOCK)
|
|
119
|
-
fcntl.fcntl(p.stderr, fcntl.F_SETFL, fcntl.fcntl(p.stderr, fcntl.F_GETFL) | os.O_NONBLOCK)
|
|
120
|
-
selector = selectors.DefaultSelector()
|
|
121
|
-
selector.register(p.stdout, selectors.EVENT_READ)
|
|
122
|
-
selector.register(p.stderr, selectors.EVENT_READ)
|
|
123
|
-
|
|
124
|
-
become_output = b''
|
|
125
|
-
try:
|
|
126
|
-
while not self.become.check_success(become_output) and not self.become.check_password_prompt(become_output):
|
|
127
|
-
events = selector.select(self._play_context.timeout)
|
|
128
|
-
if not events:
|
|
129
|
-
stdout, stderr = p.communicate()
|
|
130
|
-
raise AnsibleError('timeout waiting for privilege escalation password prompt:\n' + to_native(become_output))
|
|
131
|
-
|
|
132
|
-
for key, event in events:
|
|
133
|
-
if key.fileobj == p.stdout:
|
|
134
|
-
chunk = p.stdout.read()
|
|
135
|
-
elif key.fileobj == p.stderr:
|
|
136
|
-
chunk = p.stderr.read()
|
|
137
|
-
|
|
138
|
-
if not chunk:
|
|
139
|
-
stdout, stderr = p.communicate()
|
|
140
|
-
raise AnsibleError('privilege output closed while waiting for password prompt:\n' + to_native(become_output))
|
|
141
|
-
become_output += chunk
|
|
142
|
-
finally:
|
|
143
|
-
selector.close()
|
|
144
|
-
|
|
145
|
-
if not self.become.check_success(become_output):
|
|
146
|
-
become_pass = self.become.get_option('become_pass', playcontext=self._play_context)
|
|
147
|
-
if master is None:
|
|
148
|
-
p.stdin.write(to_bytes(become_pass, errors='surrogate_or_strict') + b'\n')
|
|
149
|
-
else:
|
|
150
|
-
os.write(master, to_bytes(become_pass, errors='surrogate_or_strict') + b'\n')
|
|
151
|
-
|
|
152
|
-
fcntl.fcntl(p.stdout, fcntl.F_SETFL, fcntl.fcntl(p.stdout, fcntl.F_GETFL) & ~os.O_NONBLOCK)
|
|
153
|
-
fcntl.fcntl(p.stderr, fcntl.F_SETFL, fcntl.fcntl(p.stderr, fcntl.F_GETFL) & ~os.O_NONBLOCK)
|
|
136
|
+
become_stdout_bytes, become_stderr_bytes = self._ensure_become_success(p, pty_primary, sudoable)
|
|
154
137
|
|
|
155
138
|
display.debug("getting output with communicate()")
|
|
156
139
|
stdout, stderr = p.communicate(in_data)
|
|
157
140
|
display.debug("done communicating")
|
|
158
141
|
|
|
142
|
+
# preserve output from privilege escalation stage as `bytes`; it may contain actual output (eg `raw`) or error messages
|
|
143
|
+
stdout = become_stdout_bytes + stdout
|
|
144
|
+
stderr = become_stderr_bytes + stderr
|
|
145
|
+
|
|
159
146
|
# finally, close the other half of the pty, if it was created
|
|
160
|
-
if
|
|
161
|
-
os.close(
|
|
147
|
+
if pty_primary:
|
|
148
|
+
os.close(pty_primary)
|
|
162
149
|
|
|
163
150
|
display.debug("done with local.exec_command()")
|
|
164
|
-
return
|
|
151
|
+
return p.returncode, stdout, stderr
|
|
152
|
+
|
|
153
|
+
def _ensure_become_success(self, p: subprocess.Popen, pty_primary: int, sudoable: bool) -> tuple[bytes, bytes]:
|
|
154
|
+
"""
|
|
155
|
+
Ensure that become succeeds, returning a tuple containing stdout captured after success and all stderr.
|
|
156
|
+
Returns immediately if `self.become` or `sudoable` are False, or `build_become_command` was not called, without performing any additional checks.
|
|
157
|
+
"""
|
|
158
|
+
if not self.become or not sudoable or not self.become._id: # _id is set by build_become_command, if it was not called, assume no become
|
|
159
|
+
return b'', b''
|
|
160
|
+
|
|
161
|
+
start_seconds = time.monotonic()
|
|
162
|
+
become_stdout = bytearray()
|
|
163
|
+
become_stderr = bytearray()
|
|
164
|
+
last_stdout_prompt_offset = 0
|
|
165
|
+
last_stderr_prompt_offset = 0
|
|
166
|
+
|
|
167
|
+
# map the buffers to their associated stream for the selector reads
|
|
168
|
+
become_capture = {
|
|
169
|
+
p.stdout: become_stdout,
|
|
170
|
+
p.stderr: become_stderr,
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
expect_password_prompt = self.become.expect_prompt()
|
|
174
|
+
sent_password = False
|
|
175
|
+
|
|
176
|
+
def become_error_msg(reason: str) -> str:
|
|
177
|
+
error_message = f'{reason} waiting for become success'
|
|
178
|
+
|
|
179
|
+
if expect_password_prompt and not sent_password:
|
|
180
|
+
error_message += ' or become password prompt'
|
|
181
|
+
|
|
182
|
+
error_message += '.'
|
|
183
|
+
|
|
184
|
+
if become_stdout:
|
|
185
|
+
error_message += f'\n>>> Standard Output\n{to_text(bytes(become_stdout))}'
|
|
186
|
+
|
|
187
|
+
if become_stderr:
|
|
188
|
+
error_message += f'\n>>> Standard Error\n{to_text(bytes(become_stderr))}'
|
|
189
|
+
|
|
190
|
+
return error_message
|
|
191
|
+
|
|
192
|
+
os.set_blocking(p.stdout.fileno(), False)
|
|
193
|
+
os.set_blocking(p.stderr.fileno(), False)
|
|
194
|
+
|
|
195
|
+
with selectors.DefaultSelector() as selector:
|
|
196
|
+
selector.register(p.stdout, selectors.EVENT_READ, 'stdout')
|
|
197
|
+
selector.register(p.stderr, selectors.EVENT_READ, 'stderr')
|
|
198
|
+
|
|
199
|
+
while not self.become.check_success(become_stdout):
|
|
200
|
+
if not selector.get_map(): # we only reach end of stream after all descriptors are EOF
|
|
201
|
+
raise AnsibleError(become_error_msg('Premature end of stream'))
|
|
202
|
+
|
|
203
|
+
if expect_password_prompt and (
|
|
204
|
+
self.become.check_password_prompt(become_stdout[last_stdout_prompt_offset:]) or
|
|
205
|
+
self.become.check_password_prompt(become_stderr[last_stderr_prompt_offset:])
|
|
206
|
+
):
|
|
207
|
+
if sent_password:
|
|
208
|
+
raise AnsibleError(become_error_msg('Duplicate become password prompt encountered'))
|
|
209
|
+
|
|
210
|
+
last_stdout_prompt_offset = len(become_stdout)
|
|
211
|
+
last_stderr_prompt_offset = len(become_stderr)
|
|
212
|
+
|
|
213
|
+
password_to_send = to_bytes(self.become.get_option('become_pass') or '') + b'\n'
|
|
214
|
+
|
|
215
|
+
if pty_primary is None:
|
|
216
|
+
p.stdin.write(password_to_send)
|
|
217
|
+
p.stdin.flush()
|
|
218
|
+
else:
|
|
219
|
+
os.write(pty_primary, password_to_send)
|
|
220
|
+
|
|
221
|
+
sent_password = True
|
|
222
|
+
|
|
223
|
+
remaining_timeout_seconds = self._become_success_timeout - (time.monotonic() - start_seconds)
|
|
224
|
+
events = selector.select(remaining_timeout_seconds) if remaining_timeout_seconds > 0 else []
|
|
225
|
+
|
|
226
|
+
if not events:
|
|
227
|
+
# ignoring remaining output after timeout to prevent hanging
|
|
228
|
+
raise AnsibleConnectionFailure(become_error_msg('Timed out'))
|
|
229
|
+
|
|
230
|
+
# read all content (non-blocking) from streams that signaled available input and append to the associated buffer
|
|
231
|
+
for key, event in events:
|
|
232
|
+
obj = t.cast(t.BinaryIO, key.fileobj)
|
|
233
|
+
|
|
234
|
+
if chunk := obj.read():
|
|
235
|
+
become_capture[obj] += chunk
|
|
236
|
+
else:
|
|
237
|
+
selector.unregister(obj) # EOF on this obj, stop polling it
|
|
238
|
+
|
|
239
|
+
os.set_blocking(p.stdout.fileno(), True)
|
|
240
|
+
os.set_blocking(p.stderr.fileno(), True)
|
|
241
|
+
|
|
242
|
+
become_stdout_bytes = bytes(become_stdout)
|
|
243
|
+
become_stderr_bytes = bytes(become_stderr)
|
|
244
|
+
|
|
245
|
+
if self.get_option('become_strip_preamble'):
|
|
246
|
+
become_stdout_bytes = self.become.strip_become_success(self.become.strip_become_prompt(become_stdout_bytes))
|
|
247
|
+
become_stderr_bytes = self.become.strip_become_prompt(become_stderr_bytes)
|
|
248
|
+
|
|
249
|
+
return become_stdout_bytes, become_stderr_bytes
|
|
250
|
+
|
|
251
|
+
@functools.cached_property
|
|
252
|
+
def _become_success_timeout(self) -> int:
|
|
253
|
+
"""Timeout value for become success in seconds."""
|
|
254
|
+
if (timeout := self.get_option('become_success_timeout')) < 1:
|
|
255
|
+
timeout = C.config.get_config_default('become_success_timeout', plugin_type='connection', plugin_name='local')
|
|
256
|
+
|
|
257
|
+
return timeout
|
|
165
258
|
|
|
166
259
|
def put_file(self, in_path: str, out_path: str) -> None:
|
|
167
|
-
|
|
260
|
+
""" transfer a file from local to local """
|
|
168
261
|
|
|
169
262
|
super(Connection, self).put_file(in_path, out_path)
|
|
170
263
|
|
|
@@ -178,17 +271,20 @@ class Connection(ConnectionBase):
|
|
|
178
271
|
shutil.copyfile(to_bytes(in_path, errors='surrogate_or_strict'), to_bytes(out_path, errors='surrogate_or_strict'))
|
|
179
272
|
except shutil.Error:
|
|
180
273
|
raise AnsibleError("failed to copy: {0} and {1} are the same".format(to_native(in_path), to_native(out_path)))
|
|
181
|
-
except
|
|
182
|
-
raise AnsibleError("
|
|
274
|
+
except OSError as ex:
|
|
275
|
+
raise AnsibleError(f"Failed to transfer file to {out_path!r}.") from ex
|
|
183
276
|
|
|
184
277
|
def fetch_file(self, in_path: str, out_path: str) -> None:
|
|
185
|
-
|
|
278
|
+
""" fetch a file from local to local -- for compatibility """
|
|
186
279
|
|
|
187
280
|
super(Connection, self).fetch_file(in_path, out_path)
|
|
188
281
|
|
|
189
282
|
display.vvv(u"FETCH {0} TO {1}".format(in_path, out_path), host=self._play_context.remote_addr)
|
|
190
283
|
self.put_file(in_path, out_path)
|
|
191
284
|
|
|
285
|
+
def reset(self) -> None:
|
|
286
|
+
pass
|
|
287
|
+
|
|
192
288
|
def close(self) -> None:
|
|
193
|
-
|
|
289
|
+
""" terminate the connection; nothing to do here """
|
|
194
290
|
self._connected = False
|
|
@@ -248,11 +248,13 @@ from ansible.errors import (
|
|
|
248
248
|
AnsibleError,
|
|
249
249
|
AnsibleFileNotFound,
|
|
250
250
|
)
|
|
251
|
-
|
|
251
|
+
|
|
252
|
+
from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text
|
|
253
|
+
from ansible.module_utils.compat.paramiko import _PARAMIKO_IMPORT_ERR as PARAMIKO_IMPORT_ERR, _paramiko as paramiko
|
|
252
254
|
from ansible.plugins.connection import ConnectionBase
|
|
253
255
|
from ansible.utils.display import Display
|
|
254
256
|
from ansible.utils.path import makedirs_safe
|
|
255
|
-
from ansible.module_utils.
|
|
257
|
+
from ansible.module_utils._internal import _deprecator
|
|
256
258
|
|
|
257
259
|
display = Display()
|
|
258
260
|
|
|
@@ -321,11 +323,20 @@ SFTP_CONNECTION_CACHE: dict[str, paramiko.sftp_client.SFTPClient] = {}
|
|
|
321
323
|
|
|
322
324
|
|
|
323
325
|
class Connection(ConnectionBase):
|
|
324
|
-
|
|
326
|
+
""" SSH based connections with Paramiko """
|
|
325
327
|
|
|
326
328
|
transport = 'paramiko'
|
|
327
329
|
_log_channel: str | None = None
|
|
328
330
|
|
|
331
|
+
def __init__(self, *args, **kwargs):
|
|
332
|
+
display.deprecated( # pylint: disable=ansible-deprecated-unnecessary-collection-name
|
|
333
|
+
msg='The paramiko connection plugin is deprecated.',
|
|
334
|
+
version='2.21',
|
|
335
|
+
deprecator=_deprecator.ANSIBLE_CORE_DEPRECATOR, # entire plugin being removed; this improves the messaging
|
|
336
|
+
)
|
|
337
|
+
|
|
338
|
+
super().__init__(*args, **kwargs)
|
|
339
|
+
|
|
329
340
|
def _cache_key(self) -> str:
|
|
330
341
|
return "%s__%s__" % (self.get_option('remote_addr'), self.get_option('remote_user'))
|
|
331
342
|
|
|
@@ -340,7 +351,7 @@ class Connection(ConnectionBase):
|
|
|
340
351
|
return self
|
|
341
352
|
|
|
342
353
|
def _set_log_channel(self, name: str) -> None:
|
|
343
|
-
|
|
354
|
+
"""Mimic paramiko.SSHClient.set_log_channel"""
|
|
344
355
|
self._log_channel = name
|
|
345
356
|
|
|
346
357
|
def _parse_proxy_command(self, port: int = 22) -> dict[str, t.Any]:
|
|
@@ -366,7 +377,7 @@ class Connection(ConnectionBase):
|
|
|
366
377
|
return sock_kwarg
|
|
367
378
|
|
|
368
379
|
def _connect_uncached(self) -> paramiko.SSHClient:
|
|
369
|
-
|
|
380
|
+
""" activates the connection object """
|
|
370
381
|
|
|
371
382
|
if paramiko is None:
|
|
372
383
|
raise AnsibleError("paramiko is not installed: %s" % to_native(PARAMIKO_IMPORT_ERR))
|
|
@@ -402,7 +413,7 @@ class Connection(ConnectionBase):
|
|
|
402
413
|
# TODO: check if we need to look at several possible locations, possible for loop
|
|
403
414
|
ssh.load_system_host_keys(ssh_known_hosts)
|
|
404
415
|
break
|
|
405
|
-
except
|
|
416
|
+
except OSError:
|
|
406
417
|
pass # file was not found, but not required to function
|
|
407
418
|
ssh.load_system_host_keys()
|
|
408
419
|
|
|
@@ -444,24 +455,23 @@ class Connection(ConnectionBase):
|
|
|
444
455
|
)
|
|
445
456
|
except paramiko.ssh_exception.BadHostKeyException as e:
|
|
446
457
|
raise AnsibleConnectionFailure('host key mismatch for %s' % e.hostname)
|
|
447
|
-
except paramiko.ssh_exception.AuthenticationException as
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
msg = to_text(e)
|
|
458
|
+
except paramiko.ssh_exception.AuthenticationException as ex:
|
|
459
|
+
raise AnsibleAuthenticationFailure() from ex
|
|
460
|
+
except Exception as ex:
|
|
461
|
+
msg = str(ex)
|
|
452
462
|
if u"PID check failed" in msg:
|
|
453
|
-
raise AnsibleError("paramiko version issue, please upgrade paramiko on the machine running ansible")
|
|
463
|
+
raise AnsibleError("paramiko version issue, please upgrade paramiko on the machine running ansible") from ex
|
|
454
464
|
elif u"Private key file is encrypted" in msg:
|
|
455
465
|
msg = 'ssh %s@%s:%s : %s\nTo connect as a different user, use -u <username>.' % (
|
|
456
466
|
self.get_option('remote_user'), self.get_options('remote_addr'), port, msg)
|
|
457
|
-
raise AnsibleConnectionFailure(msg)
|
|
467
|
+
raise AnsibleConnectionFailure(msg) from ex
|
|
458
468
|
else:
|
|
459
|
-
raise AnsibleConnectionFailure(msg)
|
|
469
|
+
raise AnsibleConnectionFailure(msg) from ex
|
|
460
470
|
|
|
461
471
|
return ssh
|
|
462
472
|
|
|
463
473
|
def exec_command(self, cmd: str, in_data: bytes | None = None, sudoable: bool = True) -> tuple[int, bytes, bytes]:
|
|
464
|
-
|
|
474
|
+
""" run a command on the remote host """
|
|
465
475
|
|
|
466
476
|
super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable)
|
|
467
477
|
|
|
@@ -541,7 +551,7 @@ class Connection(ConnectionBase):
|
|
|
541
551
|
return (chan.recv_exit_status(), no_prompt_out + stdout, no_prompt_out + stderr)
|
|
542
552
|
|
|
543
553
|
def put_file(self, in_path: str, out_path: str) -> None:
|
|
544
|
-
|
|
554
|
+
""" transfer a file from local to remote """
|
|
545
555
|
|
|
546
556
|
super(Connection, self).put_file(in_path, out_path)
|
|
547
557
|
|
|
@@ -557,8 +567,8 @@ class Connection(ConnectionBase):
|
|
|
557
567
|
|
|
558
568
|
try:
|
|
559
569
|
self.sftp.put(to_bytes(in_path, errors='surrogate_or_strict'), to_bytes(out_path, errors='surrogate_or_strict'))
|
|
560
|
-
except
|
|
561
|
-
raise AnsibleError("
|
|
570
|
+
except OSError as ex:
|
|
571
|
+
raise AnsibleError(f"Failed to transfer file to {out_path!r}.") from ex
|
|
562
572
|
|
|
563
573
|
def _connect_sftp(self) -> paramiko.sftp_client.SFTPClient:
|
|
564
574
|
|
|
@@ -570,7 +580,7 @@ class Connection(ConnectionBase):
|
|
|
570
580
|
return result
|
|
571
581
|
|
|
572
582
|
def fetch_file(self, in_path: str, out_path: str) -> None:
|
|
573
|
-
|
|
583
|
+
""" save a remote file to the specified path """
|
|
574
584
|
|
|
575
585
|
super(Connection, self).fetch_file(in_path, out_path)
|
|
576
586
|
|
|
@@ -583,8 +593,8 @@ class Connection(ConnectionBase):
|
|
|
583
593
|
|
|
584
594
|
try:
|
|
585
595
|
self.sftp.get(to_bytes(in_path, errors='surrogate_or_strict'), to_bytes(out_path, errors='surrogate_or_strict'))
|
|
586
|
-
except
|
|
587
|
-
raise AnsibleError("
|
|
596
|
+
except OSError as ex:
|
|
597
|
+
raise AnsibleError(f"Failed to transfer file from {in_path!r}.") from ex
|
|
588
598
|
|
|
589
599
|
def _any_keys_added(self) -> bool:
|
|
590
600
|
|
|
@@ -596,10 +606,10 @@ class Connection(ConnectionBase):
|
|
|
596
606
|
return False
|
|
597
607
|
|
|
598
608
|
def _save_ssh_host_keys(self, filename: str) -> None:
|
|
599
|
-
|
|
609
|
+
"""
|
|
600
610
|
not using the paramiko save_ssh_host_keys function as we want to add new SSH keys at the bottom so folks
|
|
601
611
|
don't complain about it :)
|
|
602
|
-
|
|
612
|
+
"""
|
|
603
613
|
|
|
604
614
|
if not self._any_keys_added():
|
|
605
615
|
return
|
|
@@ -632,7 +642,7 @@ class Connection(ConnectionBase):
|
|
|
632
642
|
self._connect()
|
|
633
643
|
|
|
634
644
|
def close(self) -> None:
|
|
635
|
-
|
|
645
|
+
""" terminate the connection """
|
|
636
646
|
|
|
637
647
|
cache_key = self._cache_key()
|
|
638
648
|
SSH_CONNECTION_CACHE.pop(cache_key, None)
|