ansible-core 2.18.5rc1__py3-none-any.whl → 2.19.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.
- ansible/_internal/__init__.py +53 -0
- ansible/_internal/_ansiballz.py +265 -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/_captured.py +128 -0
- ansible/_internal/_errors/_handler.py +91 -0
- ansible/_internal/_errors/_utils.py +310 -0
- ansible/_internal/_json/__init__.py +203 -0
- ansible/_internal/_json/_legacy_encoder.py +34 -0
- ansible/_internal/_json/_profiles/__init__.py +0 -0
- ansible/_internal/_json/_profiles/_cache_persistence.py +55 -0
- ansible/_internal/_json/_profiles/_inventory_legacy.py +40 -0
- ansible/_internal/_json/_profiles/_legacy.py +197 -0
- ansible/_internal/_locking.py +21 -0
- ansible/_internal/_plugins/__init__.py +0 -0
- ansible/_internal/_plugins/_cache.py +57 -0
- ansible/_internal/_task.py +78 -0
- ansible/_internal/_templating/__init__.py +10 -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 +588 -0
- ansible/_internal/_templating/_errors.py +28 -0
- ansible/_internal/_templating/_jinja_bits.py +1066 -0
- ansible/_internal/_templating/_jinja_common.py +332 -0
- ansible/_internal/_templating/_jinja_patches.py +44 -0
- ansible/_internal/_templating/_jinja_plugins.py +345 -0
- ansible/_internal/_templating/_lazy_containers.py +633 -0
- ansible/_internal/_templating/_marker_behaviors.py +103 -0
- ansible/_internal/_templating/_transform.py +63 -0
- ansible/_internal/_templating/_utils.py +107 -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 +62 -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 +18 -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 +159 -89
- ansible/cli/_ssh_askpass.py +47 -0
- ansible/cli/adhoc.py +14 -7
- ansible/cli/arguments/option_helpers.py +154 -7
- ansible/cli/config.py +43 -68
- ansible/cli/console.py +10 -8
- ansible/cli/doc.py +62 -53
- ansible/cli/galaxy.py +27 -20
- ansible/cli/inventory.py +28 -26
- ansible/cli/playbook.py +4 -12
- ansible/cli/pull.py +51 -11
- ansible/cli/scripts/ansible_connection_cli_stub.py +7 -7
- ansible/cli/vault.py +12 -11
- ansible/compat/__init__.py +2 -2
- ansible/config/base.yml +166 -112
- ansible/config/manager.py +52 -49
- ansible/constants.py +3 -4
- ansible/errors/__init__.py +277 -235
- ansible/executor/interpreter_discovery.py +28 -149
- ansible/executor/module_common.py +426 -493
- 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 +202 -151
- ansible/executor/powershell/become_wrapper.ps1 +89 -144
- ansible/executor/powershell/bootstrap_wrapper.ps1 +24 -9
- ansible/executor/powershell/coverage_wrapper.ps1 +82 -135
- ansible/executor/powershell/exec_wrapper.ps1 +462 -196
- ansible/executor/powershell/module_manifest.py +417 -265
- ansible/executor/powershell/module_wrapper.ps1 +169 -186
- 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 +161 -96
- ansible/executor/stats.py +5 -5
- ansible/executor/task_executor.py +268 -258
- ansible/executor/task_queue_manager.py +124 -90
- ansible/executor/task_result.py +183 -78
- ansible/galaxy/__init__.py +2 -2
- ansible/galaxy/api.py +22 -18
- ansible/galaxy/collection/__init__.py +1 -1
- ansible/galaxy/collection/concrete_artifact_manager.py +8 -11
- ansible/galaxy/dependency_resolution/dataclasses.py +14 -4
- ansible/galaxy/dependency_resolution/providers.py +1 -1
- ansible/galaxy/dependency_resolution/reporters.py +81 -0
- ansible/galaxy/role.py +4 -8
- ansible/galaxy/token.py +28 -21
- ansible/inventory/data.py +47 -57
- ansible/inventory/group.py +44 -72
- ansible/inventory/helpers.py +9 -0
- ansible/inventory/host.py +32 -54
- ansible/inventory/manager.py +78 -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.py +133 -0
- ansible/module_utils/_internal/_concurrent/_daemon_threading.py +1 -0
- ansible/module_utils/_internal/_dataclass_annotation_patch.py +64 -0
- ansible/module_utils/_internal/_dataclass_validation.py +217 -0
- ansible/module_utils/_internal/_datatag/__init__.py +928 -0
- ansible/module_utils/_internal/_datatag/_tags.py +38 -0
- ansible/module_utils/_internal/_debugging.py +31 -0
- ansible/module_utils/_internal/_errors.py +30 -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 +410 -0
- ansible/module_utils/_internal/_json/_profiles/_fallback_to_str.py +73 -0
- ansible/module_utils/_internal/_json/_profiles/_module_legacy_c2m.py +31 -0
- ansible/module_utils/_internal/_json/_profiles/_module_legacy_m2c.py +35 -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 +50 -0
- ansible/module_utils/_internal/_patches/__init__.py +66 -0
- ansible/module_utils/_internal/_patches/_dataclass_annotation_patch.py +55 -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_exec_context.py +49 -0
- ansible/module_utils/_internal/_testing.py +0 -0
- ansible/module_utils/_internal/_traceback.py +89 -0
- ansible/module_utils/ansible_release.py +2 -2
- ansible/module_utils/api.py +1 -2
- ansible/module_utils/basic.py +152 -120
- ansible/module_utils/common/_utils.py +24 -28
- ansible/module_utils/common/collections.py +1 -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/messages.py +108 -0
- ansible/module_utils/common/parameters.py +27 -24
- ansible/module_utils/common/process.py +2 -2
- ansible/module_utils/common/respawn.py +41 -19
- 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 +86 -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 +2 -2
- ansible/module_utils/csharp/Ansible.Basic.cs +14 -11
- ansible/module_utils/csharp/Ansible.Become.cs +1 -0
- ansible/module_utils/csharp/Ansible._Async.cs +517 -0
- ansible/module_utils/datatag.py +46 -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 +1 -1
- 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 +4 -4
- 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 +1 -2
- ansible/module_utils/facts/other/ohai.py +2 -3
- ansible/module_utils/facts/system/apparmor.py +1 -2
- ansible/module_utils/facts/system/caps.py +1 -1
- 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 +9 -8
- 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 +1 -2
- 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/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 +1 -1
- ansible/module_utils/service.py +18 -21
- ansible/module_utils/splitter.py +7 -7
- ansible/module_utils/testing.py +31 -0
- ansible/module_utils/urls.py +60 -31
- ansible/modules/add_host.py +4 -4
- ansible/modules/apt.py +60 -46
- ansible/modules/apt_key.py +19 -12
- ansible/modules/apt_repository.py +19 -16
- ansible/modules/assemble.py +6 -6
- ansible/modules/assert.py +4 -4
- ansible/modules/async_status.py +10 -12
- ansible/modules/async_wrapper.py +8 -3
- ansible/modules/blockinfile.py +6 -7
- ansible/modules/command.py +10 -17
- ansible/modules/copy.py +57 -144
- ansible/modules/cron.py +20 -15
- 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 +8 -10
- ansible/modules/fail.py +4 -4
- ansible/modules/fetch.py +4 -4
- ansible/modules/file.py +174 -133
- ansible/modules/find.py +19 -17
- ansible/modules/gather_facts.py +3 -3
- ansible/modules/get_url.py +59 -53
- ansible/modules/getent.py +7 -9
- ansible/modules/git.py +28 -25
- ansible/modules/group.py +6 -6
- ansible/modules/group_by.py +4 -4
- ansible/modules/hostname.py +13 -29
- 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 +10 -10
- ansible/modules/lineinfile.py +5 -5
- ansible/modules/meta.py +4 -4
- ansible/modules/mount_facts.py +2 -2
- ansible/modules/package.py +4 -4
- ansible/modules/package_facts.py +22 -10
- ansible/modules/pause.py +6 -6
- ansible/modules/ping.py +6 -6
- ansible/modules/pip.py +10 -11
- ansible/modules/raw.py +4 -4
- ansible/modules/reboot.py +6 -6
- ansible/modules/replace.py +9 -13
- ansible/modules/rpm_key.py +7 -8
- ansible/modules/script.py +4 -4
- ansible/modules/service.py +7 -8
- 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 +6 -6
- ansible/modules/stat.py +9 -23
- ansible/modules/subversion.py +15 -15
- ansible/modules/systemd.py +6 -6
- ansible/modules/systemd_service.py +6 -6
- ansible/modules/sysvinit.py +6 -6
- ansible/modules/tempfile.py +5 -6
- ansible/modules/template.py +6 -6
- ansible/modules/unarchive.py +32 -11
- ansible/modules/uri.py +33 -26
- ansible/modules/user.py +53 -34
- ansible/modules/validate_argument_spec.py +10 -7
- ansible/modules/wait_for.py +32 -27
- ansible/modules/wait_for_connection.py +6 -6
- ansible/modules/yum_repository.py +6 -6
- ansible/parsing/ajson.py +14 -32
- ansible/parsing/dataloader.py +99 -54
- ansible/parsing/mod_args.py +28 -44
- 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 +319 -87
- 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 +182 -132
- 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 +31 -27
- ansible/playbook/loop_control.py +2 -2
- ansible/playbook/play.py +85 -44
- ansible/playbook/play_context.py +12 -17
- ansible/playbook/playbook_include.py +14 -15
- ansible/playbook/role/__init__.py +24 -26
- 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 +13 -8
- ansible/playbook/task.py +188 -118
- ansible/playbook/task_include.py +5 -5
- ansible/plugins/__init__.py +68 -21
- ansible/plugins/action/__init__.py +209 -176
- ansible/plugins/action/add_host.py +1 -1
- ansible/plugins/action/assemble.py +1 -1
- ansible/plugins/action/assert.py +54 -66
- ansible/plugins/action/copy.py +7 -11
- 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 +4 -5
- ansible/plugins/action/gather_facts.py +7 -6
- ansible/plugins/action/group_by.py +1 -1
- ansible/plugins/action/include_vars.py +10 -11
- ansible/plugins/action/package.py +3 -6
- ansible/plugins/action/pause.py +2 -2
- ansible/plugins/action/script.py +15 -8
- ansible/plugins/action/service.py +6 -11
- ansible/plugins/action/set_fact.py +3 -12
- ansible/plugins/action/set_stats.py +3 -8
- ansible/plugins/action/template.py +35 -59
- ansible/plugins/action/unarchive.py +1 -1
- 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 +35 -44
- 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 +284 -179
- ansible/plugins/callback/default.py +99 -92
- ansible/plugins/callback/junit.py +44 -39
- ansible/plugins/callback/minimal.py +28 -25
- ansible/plugins/callback/oneline.py +28 -21
- ansible/plugins/callback/tree.py +16 -11
- ansible/plugins/connection/__init__.py +47 -34
- ansible/plugins/connection/local.py +150 -54
- ansible/plugins/connection/paramiko_ssh.py +21 -18
- ansible/plugins/connection/psrp.py +76 -165
- ansible/plugins/connection/ssh.py +301 -78
- ansible/plugins/connection/winrm.py +58 -140
- 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 +6 -2
- 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 +225 -108
- ansible/plugins/filter/encryption.py +32 -32
- 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/regex_search.yml +1 -4
- ansible/plugins/filter/split.yml +1 -1
- ansible/plugins/filter/to_nice_yaml.yml +0 -4
- 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 +97 -77
- 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 +189 -119
- ansible/plugins/inventory/toml.py +16 -126
- ansible/plugins/inventory/yaml.py +10 -8
- ansible/plugins/list.py +3 -3
- ansible/plugins/loader.py +197 -82
- ansible/plugins/lookup/__init__.py +21 -4
- ansible/plugins/lookup/config.py +21 -35
- ansible/plugins/lookup/csvfile.py +3 -2
- 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 +86 -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 +42 -36
- ansible/plugins/lookup/together.py +0 -12
- ansible/plugins/lookup/unvault.py +1 -5
- ansible/plugins/lookup/url.py +2 -8
- ansible/plugins/lookup/vars.py +16 -24
- ansible/plugins/shell/__init__.py +2 -2
- ansible/plugins/shell/cmd.py +2 -2
- ansible/plugins/shell/powershell.py +39 -22
- ansible/plugins/shell/sh.py +3 -2
- ansible/plugins/strategy/__init__.py +159 -184
- 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 +55 -21
- ansible/plugins/test/files.py +1 -1
- ansible/plugins/test/mathstuff.py +3 -3
- ansible/plugins/test/uri.py +3 -3
- ansible/plugins/vars/host_group_vars.py +7 -14
- ansible/release.py +2 -2
- ansible/template/__init__.py +370 -944
- ansible/utils/__init__.py +0 -18
- ansible/utils/_ssh_agent.py +657 -0
- ansible/utils/collection_loader/__init__.py +52 -5
- ansible/utils/collection_loader/_collection_config.py +5 -6
- ansible/utils/collection_loader/_collection_finder.py +79 -93
- ansible/utils/collection_loader/_collection_meta.py +13 -8
- ansible/utils/display.py +433 -63
- ansible/utils/encrypt.py +27 -19
- ansible/utils/fqcn.py +2 -2
- ansible/utils/hashing.py +2 -2
- ansible/utils/helpers.py +2 -2
- ansible/utils/listify.py +8 -8
- ansible/utils/lock.py +2 -2
- ansible/utils/path.py +4 -4
- ansible/utils/plugin_docs.py +14 -13
- ansible/utils/sentinel.py +4 -62
- ansible/utils/singleton.py +2 -0
- ansible/utils/ssh_functions.py +1 -1
- ansible/utils/unsafe_proxy.py +23 -332
- ansible/utils/vars.py +51 -8
- ansible/utils/version.py +2 -2
- ansible/vars/clean.py +5 -5
- ansible/vars/hostvars.py +60 -90
- ansible/vars/manager.py +206 -282
- ansible/vars/reserved.py +8 -9
- ansible_core-2.19.0b2.dist-info/BSD-3-Clause.txt +28 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/METADATA +5 -4
- ansible_core-2.19.0b2.dist-info/RECORD +1072 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/WHEEL +1 -1
- 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 +1 -1
- ansible_test/_data/requirements/sanity.import.plugin.txt +2 -2
- ansible_test/_data/requirements/sanity.pylint.txt +4 -4
- 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 +1 -0
- ansible_test/_internal/ansible_util.py +2 -0
- 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 -0
- 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 +1 -0
- 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 +2 -1
- 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 +4 -0
- 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 +2 -1
- 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 +1 -0
- 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 +16 -1
- 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 +1 -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 +24 -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 +1 -0
- ansible_test/_internal/commands/units/__init__.py +1 -0
- 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 +2 -0
- 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/delegation.py +1 -0
- 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 +1 -0
- ansible_test/_internal/http.py +1 -0
- ansible_test/_internal/init.py +1 -0
- ansible_test/_internal/inventory.py +35 -3
- ansible_test/_internal/io.py +1 -0
- ansible_test/_internal/metadata.py +1 -0
- ansible_test/_internal/payload.py +1 -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 +1 -0
- ansible_test/_internal/pypi_proxy.py +6 -5
- ansible_test/_internal/python_requirements.py +1 -0
- ansible_test/_internal/ssh.py +1 -0
- ansible_test/_internal/target.py +1 -0
- ansible_test/_internal/test.py +3 -2
- ansible_test/_internal/thread.py +1 -0
- ansible_test/_internal/timeout.py +1 -0
- ansible_test/_internal/util.py +1 -0
- ansible_test/_internal/util_common.py +5 -2
- 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 +7 -5
- ansible_test/_util/controller/sanity/pylint/config/ansible-test.cfg +7 -5
- ansible_test/_util/controller/sanity/pylint/config/code-smell.cfg +7 -5
- ansible_test/_util/controller/sanity/pylint/config/collection.cfg +3 -5
- ansible_test/_util/controller/sanity/pylint/config/default.cfg +7 -7
- ansible_test/_util/controller/sanity/pylint/plugins/deprecated.py +1 -13
- 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/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 +35 -27
- 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.5rc1.dist-info/RECORD +0 -992
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/Apache-License.txt +0 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/COPYING +0 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/MIT-license.txt +0 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/PSF-license.txt +0 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/entry_points.txt +0 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/simplified_bsd.txt +0 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/top_level.txt +0 -0
ansible/plugins/loader.py
CHANGED
@@ -6,35 +6,41 @@
|
|
6
6
|
|
7
7
|
from __future__ import annotations
|
8
8
|
|
9
|
+
import functools
|
9
10
|
import glob
|
10
11
|
import os
|
11
12
|
import os.path
|
12
13
|
import pkgutil
|
13
14
|
import sys
|
15
|
+
import types
|
14
16
|
import warnings
|
17
|
+
import typing as t
|
18
|
+
|
19
|
+
import yaml
|
15
20
|
|
16
21
|
from collections import defaultdict, namedtuple
|
17
22
|
from importlib import import_module
|
18
|
-
from
|
19
|
-
|
20
|
-
import ansible.module_utils.compat.typing as t
|
21
|
-
|
22
|
-
from .filter import AnsibleJinja2Filter
|
23
|
-
from .test import AnsibleJinja2Test
|
23
|
+
from yaml.parser import ParserError
|
24
24
|
|
25
25
|
from ansible import __version__ as ansible_version
|
26
|
-
from ansible import constants as C
|
26
|
+
from ansible import _internal, constants as C
|
27
27
|
from ansible.errors import AnsibleError, AnsiblePluginCircularRedirect, AnsiblePluginRemovedError, AnsibleCollectionUnsupportedVersionError
|
28
28
|
from ansible.module_utils.common.text.converters import to_bytes, to_text, to_native
|
29
29
|
from ansible.module_utils.six import string_types
|
30
|
-
from ansible.parsing.utils.yaml import from_yaml
|
31
30
|
from ansible.parsing.yaml.loader import AnsibleLoader
|
31
|
+
from ansible._internal._yaml._loader import AnsibleInstrumentedLoader
|
32
32
|
from ansible.plugins import get_plugin_class, MODULE_CACHE, PATH_CACHE, PLUGIN_PATH_CACHE
|
33
33
|
from ansible.utils.collection_loader import AnsibleCollectionConfig, AnsibleCollectionRef
|
34
34
|
from ansible.utils.collection_loader._collection_finder import _AnsibleCollectionFinder, _get_collection_metadata
|
35
35
|
from ansible.utils.display import Display
|
36
36
|
from ansible.utils.plugin_docs import add_fragments
|
37
|
-
from ansible.
|
37
|
+
from ansible._internal._datatag import _tags
|
38
|
+
|
39
|
+
from . import _AnsiblePluginInfoMixin
|
40
|
+
from .filter import AnsibleJinja2Filter
|
41
|
+
from .test import AnsibleJinja2Test
|
42
|
+
from .._internal._plugins import _cache
|
43
|
+
from ..module_utils.common.messages import PluginInfo
|
38
44
|
|
39
45
|
# TODO: take the packaging dep, or vendor SpecifierSet?
|
40
46
|
|
@@ -47,18 +53,30 @@ except ImportError:
|
|
47
53
|
|
48
54
|
import importlib.util
|
49
55
|
|
56
|
+
if t.TYPE_CHECKING:
|
57
|
+
from ansible.plugins.cache import BaseCacheModule
|
58
|
+
|
50
59
|
_PLUGIN_FILTERS = defaultdict(frozenset) # type: t.DefaultDict[str, frozenset]
|
51
60
|
display = Display()
|
52
61
|
|
53
62
|
get_with_context_result = namedtuple('get_with_context_result', ['object', 'plugin_load_context'])
|
54
63
|
|
55
64
|
|
56
|
-
|
65
|
+
@functools.cache
|
66
|
+
def get_all_plugin_loaders() -> list[tuple[str, 'PluginLoader']]:
|
57
67
|
return [(name, obj) for (name, obj) in globals().items() if isinstance(obj, PluginLoader)]
|
58
68
|
|
59
69
|
|
70
|
+
@functools.cache
|
71
|
+
def get_plugin_loader_namespace() -> types.SimpleNamespace:
|
72
|
+
ns = types.SimpleNamespace()
|
73
|
+
for name, obj in get_all_plugin_loaders():
|
74
|
+
setattr(ns, name, obj)
|
75
|
+
return ns
|
76
|
+
|
77
|
+
|
60
78
|
def add_all_plugin_dirs(path):
|
61
|
-
|
79
|
+
""" add any existing plugin dirs in the path provided """
|
62
80
|
b_path = os.path.expanduser(to_bytes(path, errors='surrogate_or_strict'))
|
63
81
|
if os.path.isdir(b_path):
|
64
82
|
for name, obj in get_all_plugin_loaders():
|
@@ -199,12 +217,12 @@ class PluginLoadContext(object):
|
|
199
217
|
|
200
218
|
|
201
219
|
class PluginLoader:
|
202
|
-
|
220
|
+
"""
|
203
221
|
PluginLoader loads plugins from the configured plugin directories.
|
204
222
|
|
205
223
|
It searches for plugins by iterating through the combined list of play basedirs, configured
|
206
224
|
paths, and the python path. The first match is used.
|
207
|
-
|
225
|
+
"""
|
208
226
|
|
209
227
|
def __init__(self, class_name, package, config, subdir, aliases=None, required_base_class=None):
|
210
228
|
aliases = {} if aliases is None else aliases
|
@@ -267,9 +285,9 @@ class PluginLoader:
|
|
267
285
|
self._searched_paths = set()
|
268
286
|
|
269
287
|
def __setstate__(self, data):
|
270
|
-
|
288
|
+
"""
|
271
289
|
Deserializer.
|
272
|
-
|
290
|
+
"""
|
273
291
|
|
274
292
|
class_name = data.get('class_name')
|
275
293
|
package = data.get('package')
|
@@ -286,9 +304,9 @@ class PluginLoader:
|
|
286
304
|
self._searched_paths = data.get('_searched_paths', set())
|
287
305
|
|
288
306
|
def __getstate__(self):
|
289
|
-
|
307
|
+
"""
|
290
308
|
Serializer.
|
291
|
-
|
309
|
+
"""
|
292
310
|
|
293
311
|
return dict(
|
294
312
|
class_name=self.class_name,
|
@@ -304,7 +322,7 @@ class PluginLoader:
|
|
304
322
|
)
|
305
323
|
|
306
324
|
def format_paths(self, paths):
|
307
|
-
|
325
|
+
""" Returns a string suitable for printing of the search path """
|
308
326
|
|
309
327
|
# Uses a list to get the order right
|
310
328
|
ret = []
|
@@ -326,7 +344,7 @@ class PluginLoader:
|
|
326
344
|
return results
|
327
345
|
|
328
346
|
def _get_package_paths(self, subdirs=True):
|
329
|
-
|
347
|
+
""" Gets the path of a Python package """
|
330
348
|
|
331
349
|
if not self.package:
|
332
350
|
return []
|
@@ -341,7 +359,7 @@ class PluginLoader:
|
|
341
359
|
return [self.package_path]
|
342
360
|
|
343
361
|
def _get_paths_with_context(self, subdirs=True):
|
344
|
-
|
362
|
+
""" Return a list of PluginPathContext objects to search for plugins in """
|
345
363
|
|
346
364
|
# FIXME: This is potentially buggy if subdirs is sometimes True and sometimes False.
|
347
365
|
# In current usage, everything calls this with subdirs=True except for module_utils_loader and ansible-doc
|
@@ -394,13 +412,13 @@ class PluginLoader:
|
|
394
412
|
return ret
|
395
413
|
|
396
414
|
def _get_paths(self, subdirs=True):
|
397
|
-
|
415
|
+
""" Return a list of paths to search for plugins in """
|
398
416
|
|
399
417
|
paths_with_context = self._get_paths_with_context(subdirs=subdirs)
|
400
418
|
return [path_with_context.path for path_with_context in paths_with_context]
|
401
419
|
|
402
420
|
def _load_config_defs(self, name, module, path):
|
403
|
-
|
421
|
+
""" Reads plugin docs to find configuration setting definitions, to push to config manager for later use """
|
404
422
|
|
405
423
|
# plugins w/o class name don't support config
|
406
424
|
if self.class_name:
|
@@ -408,12 +426,15 @@ class PluginLoader:
|
|
408
426
|
|
409
427
|
# if type name != 'module_doc_fragment':
|
410
428
|
if type_name in C.CONFIGURABLE_PLUGINS and not C.config.has_configuration_definition(type_name, name):
|
411
|
-
|
429
|
+
documentation_source = getattr(module, 'DOCUMENTATION', '')
|
430
|
+
try:
|
431
|
+
dstring = yaml.load(_tags.Origin(path=path).tag(documentation_source), Loader=AnsibleLoader)
|
432
|
+
except ParserError as e:
|
433
|
+
raise AnsibleError(f"plugin {name} has malformed documentation!") from e
|
412
434
|
|
413
435
|
# TODO: allow configurable plugins to use sidecar
|
414
436
|
# if not dstring:
|
415
437
|
# filename, cn = find_plugin_docfile( name, type_name, self, [os.path.dirname(path)], C.YAML_DOC_EXTENSIONS)
|
416
|
-
# # TODO: dstring = AnsibleLoader(, file_name=path).get_single_data()
|
417
438
|
|
418
439
|
if dstring:
|
419
440
|
add_fragments(dstring, path, fragment_loader=fragment_loader, is_module=(type_name == 'module'))
|
@@ -423,7 +444,7 @@ class PluginLoader:
|
|
423
444
|
display.debug('Loaded config def from plugin (%s/%s)' % (type_name, name))
|
424
445
|
|
425
446
|
def add_directory(self, directory, with_subdir=False):
|
426
|
-
|
447
|
+
""" Adds an additional directory to the search path """
|
427
448
|
|
428
449
|
directory = os.path.realpath(directory)
|
429
450
|
|
@@ -497,10 +518,19 @@ class PluginLoader:
|
|
497
518
|
removal_date = tombstone.get('removal_date')
|
498
519
|
removal_version = tombstone.get('removal_version')
|
499
520
|
warning_text = tombstone.get('warning_text') or ''
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
521
|
+
warning_plugin_type = "module" if self.type == "modules" else f'{self.type} plugin'
|
522
|
+
warning_text = f'The {fq_name!r} {warning_plugin_type} has been removed.{" " if warning_text else ""}{warning_text}'
|
523
|
+
removed_msg = display._get_deprecation_message_with_plugin_info(
|
524
|
+
msg=warning_text,
|
525
|
+
version=removal_version,
|
526
|
+
date=removal_date,
|
527
|
+
removed=True,
|
528
|
+
plugin=PluginInfo(
|
529
|
+
requested_name=acr.collection,
|
530
|
+
resolved_name=acr.collection,
|
531
|
+
type='collection',
|
532
|
+
),
|
533
|
+
)
|
504
534
|
plugin_load_context.removal_date = removal_date
|
505
535
|
plugin_load_context.removal_version = removal_version
|
506
536
|
plugin_load_context.resolved = True
|
@@ -577,15 +607,22 @@ class PluginLoader:
|
|
577
607
|
'found fuzzy extension match for {0} in {1}'.format(full_name, acr.collection), action_plugin)
|
578
608
|
|
579
609
|
def find_plugin(self, name, mod_type='', ignore_deprecated=False, check_aliases=False, collection_list=None):
|
580
|
-
|
610
|
+
""" Find a plugin named name """
|
581
611
|
result = self.find_plugin_with_context(name, mod_type, ignore_deprecated, check_aliases, collection_list)
|
582
612
|
if result.resolved and result.plugin_resolved_path:
|
583
613
|
return result.plugin_resolved_path
|
584
614
|
|
585
615
|
return None
|
586
616
|
|
587
|
-
def find_plugin_with_context(
|
588
|
-
|
617
|
+
def find_plugin_with_context(
|
618
|
+
self,
|
619
|
+
name: str,
|
620
|
+
mod_type: str = '',
|
621
|
+
ignore_deprecated: bool = False,
|
622
|
+
check_aliases: bool = False,
|
623
|
+
collection_list: list[str] | None = None,
|
624
|
+
) -> PluginLoadContext:
|
625
|
+
""" Find a plugin named name, returning contextual info about the load, recursively resolving redirection """
|
589
626
|
plugin_load_context = PluginLoadContext()
|
590
627
|
plugin_load_context.original_name = name
|
591
628
|
while True:
|
@@ -795,7 +832,7 @@ class PluginLoader:
|
|
795
832
|
return plugin_load_context.nope('{0} is not eligible for last-chance resolution'.format(name))
|
796
833
|
|
797
834
|
def has_plugin(self, name, collection_list=None):
|
798
|
-
|
835
|
+
""" Checks if a plugin named name exists """
|
799
836
|
|
800
837
|
try:
|
801
838
|
return self.find_plugin(name, collection_list=collection_list) is not None
|
@@ -838,12 +875,20 @@ class PluginLoader:
|
|
838
875
|
|
839
876
|
return module
|
840
877
|
|
841
|
-
def _update_object(
|
878
|
+
def _update_object(
|
879
|
+
self,
|
880
|
+
obj: _AnsiblePluginInfoMixin,
|
881
|
+
name: str,
|
882
|
+
path: str,
|
883
|
+
redirected_names: list[str] | None = None,
|
884
|
+
resolved: str | None = None,
|
885
|
+
) -> None:
|
886
|
+
# DTFIX-RELEASE: clean this up- standardize types, document, split/remove redundant bits
|
842
887
|
|
843
888
|
# set extra info on the module, in case we want it later
|
844
|
-
|
845
|
-
|
846
|
-
|
889
|
+
obj._original_path = path
|
890
|
+
obj._load_name = name
|
891
|
+
obj._redirected_names = redirected_names or []
|
847
892
|
|
848
893
|
names = []
|
849
894
|
if resolved:
|
@@ -854,25 +899,23 @@ class PluginLoader:
|
|
854
899
|
if not names:
|
855
900
|
raise AnsibleError(f"Missing FQCN for plugin source {name}")
|
856
901
|
|
857
|
-
|
858
|
-
|
902
|
+
obj.ansible_aliases = names
|
903
|
+
obj.ansible_name = names[0]
|
859
904
|
|
860
905
|
def get(self, name, *args, **kwargs):
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
# Manually removing the unsafe wrapper prevents such issues.
|
875
|
-
name = name._strip_unsafe()
|
906
|
+
ctx = self.get_with_context(name, *args, **kwargs)
|
907
|
+
is_core_plugin = ctx.plugin_load_context.plugin_resolved_collection == 'ansible.builtin'
|
908
|
+
if self.class_name == 'StrategyModule' and not is_core_plugin:
|
909
|
+
display.deprecated( # pylint: disable=ansible-deprecated-no-version
|
910
|
+
'Use of strategy plugins not included in ansible.builtin are deprecated and do not carry '
|
911
|
+
'any backwards compatibility guarantees. No alternative for third party strategy plugins '
|
912
|
+
'is currently planned.'
|
913
|
+
)
|
914
|
+
|
915
|
+
return ctx.object
|
916
|
+
|
917
|
+
def get_with_context(self, name, *args, **kwargs) -> get_with_context_result:
|
918
|
+
""" instantiates a plugin of the given name using arguments """
|
876
919
|
|
877
920
|
found_in_cache = True
|
878
921
|
class_only = kwargs.pop('class_only', False)
|
@@ -950,7 +993,7 @@ class PluginLoader:
|
|
950
993
|
return get_with_context_result(obj, plugin_load_context)
|
951
994
|
|
952
995
|
def _display_plugin_load(self, class_name, name, searched_paths, path, found_in_cache=None, class_only=None):
|
953
|
-
|
996
|
+
""" formats data to display debug info for plugin loading, also avoids processing unless really needed """
|
954
997
|
if C.DEFAULT_DEBUG:
|
955
998
|
msg = 'Loading %s \'%s\' from %s' % (class_name, os.path.basename(name), path)
|
956
999
|
|
@@ -963,7 +1006,7 @@ class PluginLoader:
|
|
963
1006
|
display.debug(msg)
|
964
1007
|
|
965
1008
|
def all(self, *args, **kwargs):
|
966
|
-
|
1009
|
+
"""
|
967
1010
|
Iterate through all plugins of this type, in configured paths (no collections)
|
968
1011
|
|
969
1012
|
A plugin loader is initialized with a specific type. This function is an iterator returning
|
@@ -984,7 +1027,7 @@ class PluginLoader:
|
|
984
1027
|
want to manage their own deduplication of the plugins.
|
985
1028
|
:*args: Any extra arguments are passed to each plugin when it is instantiated.
|
986
1029
|
:**kwargs: Any extra keyword arguments are passed to each plugin when it is instantiated.
|
987
|
-
|
1030
|
+
"""
|
988
1031
|
# TODO: Change the signature of this method to:
|
989
1032
|
# def all(return_type='instance', args=None, kwargs=None):
|
990
1033
|
# if args is None: args = []
|
@@ -1117,6 +1160,21 @@ class PluginLoader:
|
|
1117
1160
|
yield obj
|
1118
1161
|
|
1119
1162
|
|
1163
|
+
class _CacheLoader(PluginLoader):
|
1164
|
+
"""Customized loader for cache plugins that wraps the requested plugin with an interposer that schema-qualifies keys and JSON encodes the values."""
|
1165
|
+
|
1166
|
+
def get(self, name: str, *args, **kwargs) -> BaseCacheModule:
|
1167
|
+
plugin = super().get(name, *args, **kwargs)
|
1168
|
+
|
1169
|
+
if not plugin:
|
1170
|
+
raise AnsibleError(f'Unable to load the cache plugin {name!r}.')
|
1171
|
+
|
1172
|
+
if plugin._persistent:
|
1173
|
+
return _cache.PluginInterposer(plugin)
|
1174
|
+
|
1175
|
+
return plugin
|
1176
|
+
|
1177
|
+
|
1120
1178
|
class Jinja2Loader(PluginLoader):
|
1121
1179
|
"""
|
1122
1180
|
PluginLoader optimized for Jinja2 plugins
|
@@ -1125,10 +1183,12 @@ class Jinja2Loader(PluginLoader):
|
|
1125
1183
|
We need to do a few things differently in the base class because of file == plugin
|
1126
1184
|
assumptions and dedupe logic.
|
1127
1185
|
"""
|
1128
|
-
|
1186
|
+
|
1187
|
+
def __init__(self, class_name, package, config, subdir, plugin_wrapper_type, aliases=None, required_base_class=None) -> None:
|
1129
1188
|
super(Jinja2Loader, self).__init__(class_name, package, config, subdir, aliases=aliases, required_base_class=required_base_class)
|
1130
1189
|
self._plugin_wrapper_type = plugin_wrapper_type
|
1131
|
-
self.
|
1190
|
+
self._plugin_type_friendly_name = 'filter' if plugin_wrapper_type is AnsibleJinja2Filter else 'test'
|
1191
|
+
self._cached_non_collection_wrappers: dict[str, AnsibleJinja2Filter | AnsibleJinja2Test | _DeferredPluginLoadFailure] = {}
|
1132
1192
|
|
1133
1193
|
def _clear_caches(self):
|
1134
1194
|
super(Jinja2Loader, self)._clear_caches()
|
@@ -1141,6 +1201,36 @@ class Jinja2Loader(PluginLoader):
|
|
1141
1201
|
def method_map_name(self):
|
1142
1202
|
return get_plugin_class(self.class_name) + 's'
|
1143
1203
|
|
1204
|
+
def _wrap_func(self, name: str, resolved: str, func: t.Callable) -> AnsibleJinja2Test | AnsibleJinja2Filter:
|
1205
|
+
"""Wrap a Jinja builtin function in a `AnsibleJinja2Plugin` instance."""
|
1206
|
+
try:
|
1207
|
+
path = sys.modules[func.__module__].__file__
|
1208
|
+
except AttributeError:
|
1209
|
+
path = None
|
1210
|
+
|
1211
|
+
wrapper = self._plugin_wrapper_type(func)
|
1212
|
+
|
1213
|
+
self._update_object(obj=wrapper, name=name, path=path, resolved=resolved)
|
1214
|
+
|
1215
|
+
return wrapper
|
1216
|
+
|
1217
|
+
def _wrap_funcs(self, plugins: dict[str, t.Callable], aliases: dict[str, str]) -> dict[str, AnsibleJinja2Test | AnsibleJinja2Filter]:
|
1218
|
+
"""Map a dictionary of Jinja builtin functions to one containing `AnsibleJinja2Plugin` instances."""
|
1219
|
+
wrappers: dict[str, AnsibleJinja2Test | AnsibleJinja2Filter] = {}
|
1220
|
+
|
1221
|
+
for load_name, func in plugins.items():
|
1222
|
+
name = aliases.get(load_name, load_name)
|
1223
|
+
resolved = f'ansible.builtin.{name}'
|
1224
|
+
|
1225
|
+
wrappers[load_name] = self._wrap_func(load_name, resolved, func)
|
1226
|
+
|
1227
|
+
if resolved not in wrappers:
|
1228
|
+
# When the resolved name hasn't been cached, do so.
|
1229
|
+
# Functions that have aliases will appear more than once, and we don't need to overwrite them.
|
1230
|
+
wrappers[resolved] = self._wrap_func(resolved, resolved, func)
|
1231
|
+
|
1232
|
+
return wrappers
|
1233
|
+
|
1144
1234
|
def get_contained_plugins(self, collection, plugin_path, name):
|
1145
1235
|
|
1146
1236
|
plugins = []
|
@@ -1179,11 +1269,13 @@ class Jinja2Loader(PluginLoader):
|
|
1179
1269
|
|
1180
1270
|
# FUTURE: now that the resulting plugins are closer, refactor base class method with some extra
|
1181
1271
|
# hooks so we can avoid all the duplicated plugin metadata logic, and also cache the collection results properly here
|
1182
|
-
def get_with_context(self, name, *args, **kwargs):
|
1272
|
+
def get_with_context(self, name: str, *args, **kwargs) -> get_with_context_result:
|
1183
1273
|
# pop N/A kwargs to avoid passthrough to parent methods
|
1184
1274
|
kwargs.pop('class_only', False)
|
1185
1275
|
kwargs.pop('collection_list', None)
|
1186
1276
|
|
1277
|
+
requested_name = name
|
1278
|
+
|
1187
1279
|
context = PluginLoadContext()
|
1188
1280
|
|
1189
1281
|
# avoid collection path for legacy
|
@@ -1193,6 +1285,9 @@ class Jinja2Loader(PluginLoader):
|
|
1193
1285
|
|
1194
1286
|
# check for stuff loaded via legacy/builtin paths first
|
1195
1287
|
if known_plugin := self._cached_non_collection_wrappers.get(name):
|
1288
|
+
if isinstance(known_plugin, _DeferredPluginLoadFailure):
|
1289
|
+
raise known_plugin.ex
|
1290
|
+
|
1196
1291
|
context.resolved = True
|
1197
1292
|
context.plugin_resolved_name = name
|
1198
1293
|
context.plugin_resolved_path = known_plugin._original_path
|
@@ -1219,7 +1314,7 @@ class Jinja2Loader(PluginLoader):
|
|
1219
1314
|
ts = _get_collection_metadata(acr.collection)
|
1220
1315
|
except ValueError as e:
|
1221
1316
|
# no collection
|
1222
|
-
raise KeyError('Invalid plugin FQCN ({0}): {1}'.format(key, to_native(e)))
|
1317
|
+
raise KeyError('Invalid plugin FQCN ({0}): {1}'.format(key, to_native(e))) from e
|
1223
1318
|
|
1224
1319
|
# TODO: implement cycle detection (unified across collection redir as well)
|
1225
1320
|
routing_entry = ts.get('plugin_routing', {}).get(self.type, {}).get(leaf_key, {})
|
@@ -1241,11 +1336,19 @@ class Jinja2Loader(PluginLoader):
|
|
1241
1336
|
warning_text = tombstone_entry.get('warning_text') or ''
|
1242
1337
|
removal_date = tombstone_entry.get('removal_date')
|
1243
1338
|
removal_version = tombstone_entry.get('removal_version')
|
1244
|
-
|
1245
|
-
|
1246
|
-
|
1247
|
-
|
1248
|
-
|
1339
|
+
warning_text = f'The {key!r} {self.type} plugin has been removed.{" " if warning_text else ""}{warning_text}'
|
1340
|
+
|
1341
|
+
exc_msg = display._get_deprecation_message_with_plugin_info(
|
1342
|
+
msg=warning_text,
|
1343
|
+
version=removal_version,
|
1344
|
+
date=removal_date,
|
1345
|
+
removed=True,
|
1346
|
+
plugin=PluginInfo(
|
1347
|
+
requested_name=acr.collection,
|
1348
|
+
resolved_name=acr.collection,
|
1349
|
+
type='collection',
|
1350
|
+
),
|
1351
|
+
)
|
1249
1352
|
|
1250
1353
|
raise AnsiblePluginRemovedError(exc_msg)
|
1251
1354
|
|
@@ -1297,20 +1400,16 @@ class Jinja2Loader(PluginLoader):
|
|
1297
1400
|
plugin = self._plugin_wrapper_type(func)
|
1298
1401
|
if plugin:
|
1299
1402
|
context = plugin_impl.plugin_load_context
|
1300
|
-
self._update_object(plugin,
|
1403
|
+
self._update_object(plugin, requested_name, plugin_impl.object._original_path, resolved=fq_name)
|
1301
1404
|
# context will have filename, which for tests/filters might not be correct
|
1302
1405
|
context._resolved_fqcn = plugin.ansible_name
|
1303
1406
|
# FIXME: once we start caching these results, we'll be missing functions that would have loaded later
|
1304
1407
|
break # go to next file as it can override if dupe (dont break both loops)
|
1305
1408
|
|
1306
|
-
except AnsiblePluginRemovedError as apre:
|
1307
|
-
raise AnsibleError(to_native(apre), 0, orig_exc=apre)
|
1308
1409
|
except (AnsibleError, KeyError):
|
1309
1410
|
raise
|
1310
1411
|
except Exception as ex:
|
1311
|
-
|
1312
|
-
display.vvv('Unexpected error during Jinja2 plugin loading: {0}'.format(format_exc()))
|
1313
|
-
raise AnsibleError(to_native(ex), 0, orig_exc=ex)
|
1412
|
+
raise AnsibleError('An unexpected error occurred during Jinja2 plugin loading.') from ex
|
1314
1413
|
|
1315
1414
|
return get_with_context_result(plugin, context)
|
1316
1415
|
|
@@ -1324,10 +1423,13 @@ class Jinja2Loader(PluginLoader):
|
|
1324
1423
|
raise AnsibleError('Do not set both path_only and class_only when calling PluginLoader.all()')
|
1325
1424
|
|
1326
1425
|
self._ensure_non_collection_wrappers(*args, **kwargs)
|
1426
|
+
|
1427
|
+
plugins = [plugin for plugin in self._cached_non_collection_wrappers.values() if not isinstance(plugin, _DeferredPluginLoadFailure)]
|
1428
|
+
|
1327
1429
|
if path_only:
|
1328
|
-
yield from (w._original_path for w in
|
1430
|
+
yield from (w._original_path for w in plugins)
|
1329
1431
|
else:
|
1330
|
-
yield from (w for w in
|
1432
|
+
yield from (w for w in plugins)
|
1331
1433
|
|
1332
1434
|
def _ensure_non_collection_wrappers(self, *args, **kwargs):
|
1333
1435
|
if self._cached_non_collection_wrappers:
|
@@ -1354,21 +1456,26 @@ class Jinja2Loader(PluginLoader):
|
|
1354
1456
|
display.debug("%s skipped due to a defined plugin filter" % plugin_name)
|
1355
1457
|
continue
|
1356
1458
|
|
1357
|
-
# the plugin class returned by the loader may host multiple Jinja plugins, but we wrap each plugin in
|
1358
|
-
# its own surrogate wrapper instance here to ease the bookkeeping...
|
1359
|
-
wrapper = self._plugin_wrapper_type(plugins[plugin_name])
|
1360
1459
|
fqcn = plugin_name
|
1361
1460
|
collection = '.'.join(p_map.ansible_name.split('.')[:2]) if p_map.ansible_name.count('.') >= 2 else ''
|
1362
1461
|
if not plugin_name.startswith(collection):
|
1363
1462
|
fqcn = f"{collection}.{plugin_name}"
|
1364
1463
|
|
1365
|
-
self._update_object(wrapper, plugin_name, p_map._original_path, resolved=fqcn)
|
1366
|
-
|
1367
1464
|
target_names = {plugin_name, fqcn}
|
1465
|
+
|
1368
1466
|
if is_builtin:
|
1369
1467
|
target_names.add(f'ansible.builtin.{plugin_name}')
|
1370
1468
|
|
1371
1469
|
for target_name in target_names:
|
1470
|
+
# the plugin class returned by the loader may host multiple Jinja plugins, but we wrap each plugin in
|
1471
|
+
# its own surrogate wrapper instance here to ease the bookkeeping...
|
1472
|
+
try:
|
1473
|
+
wrapper = self._plugin_wrapper_type(plugins[plugin_name])
|
1474
|
+
except Exception as ex:
|
1475
|
+
wrapper = _DeferredPluginLoadFailure(ex)
|
1476
|
+
|
1477
|
+
self._update_object(obj=wrapper, name=target_name, path=p_map._original_path, resolved=fqcn)
|
1478
|
+
|
1372
1479
|
if existing_plugin := self._cached_non_collection_wrappers.get(target_name):
|
1373
1480
|
display.debug(f'Jinja plugin {target_name} from {p_map._original_path} skipped; '
|
1374
1481
|
f'shadowed by plugin from {existing_plugin._original_path})')
|
@@ -1377,6 +1484,13 @@ class Jinja2Loader(PluginLoader):
|
|
1377
1484
|
self._cached_non_collection_wrappers[target_name] = wrapper
|
1378
1485
|
|
1379
1486
|
|
1487
|
+
class _DeferredPluginLoadFailure:
|
1488
|
+
"""Represents a plugin which failed to load. For internal use only within plugin loader."""
|
1489
|
+
|
1490
|
+
def __init__(self, ex: Exception) -> None:
|
1491
|
+
self.ex = ex
|
1492
|
+
|
1493
|
+
|
1380
1494
|
def get_fqcr_and_name(resource, collection='ansible.builtin'):
|
1381
1495
|
if '.' not in resource:
|
1382
1496
|
name = resource
|
@@ -1400,7 +1514,7 @@ def _load_plugin_filter():
|
|
1400
1514
|
if os.path.exists(filter_cfg):
|
1401
1515
|
with open(filter_cfg, 'rb') as f:
|
1402
1516
|
try:
|
1403
|
-
filter_data =
|
1517
|
+
filter_data = yaml.load(f, Loader=AnsibleInstrumentedLoader)
|
1404
1518
|
except Exception as e:
|
1405
1519
|
display.warning(u'The plugin filter file, {0} was not parsable.'
|
1406
1520
|
u' Skipping: {1}'.format(filter_cfg, to_text(e)))
|
@@ -1489,7 +1603,8 @@ def _configure_collection_loader(prefix_collections_path=None):
|
|
1489
1603
|
if prefix_collections_path is None:
|
1490
1604
|
prefix_collections_path = []
|
1491
1605
|
|
1492
|
-
|
1606
|
+
# insert the internal ansible._protomatter collection up front
|
1607
|
+
paths = [os.path.dirname(_internal.__file__)] + list(prefix_collections_path) + C.COLLECTIONS_PATHS
|
1493
1608
|
finder = _AnsibleCollectionFinder(paths, C.COLLECTIONS_SCAN_SYS_PATH)
|
1494
1609
|
finder._install()
|
1495
1610
|
|
@@ -1529,7 +1644,7 @@ action_loader = PluginLoader(
|
|
1529
1644
|
required_base_class='ActionBase',
|
1530
1645
|
)
|
1531
1646
|
|
1532
|
-
cache_loader =
|
1647
|
+
cache_loader = _CacheLoader(
|
1533
1648
|
'CacheModule',
|
1534
1649
|
'ansible.plugins.cache',
|
1535
1650
|
C.DEFAULT_CACHE_PLUGIN_PATH,
|
@@ -23,14 +23,31 @@ from ansible.errors import AnsibleFileNotFound
|
|
23
23
|
from ansible.plugins import AnsiblePlugin
|
24
24
|
from ansible.utils.display import Display
|
25
25
|
|
26
|
+
import typing as t
|
27
|
+
|
28
|
+
if t.TYPE_CHECKING:
|
29
|
+
from ansible.parsing import dataloader as _dataloader
|
30
|
+
from ansible import template as _template
|
31
|
+
|
26
32
|
display = Display()
|
27
33
|
|
28
34
|
__all__ = ['LookupBase']
|
29
35
|
|
30
36
|
|
31
37
|
class LookupBase(AnsiblePlugin):
|
38
|
+
accept_args_markers: t.ClassVar[bool] = False
|
39
|
+
"""
|
40
|
+
When `False`, plugin invocation is skipped when a top-level argument is a `Marker`, with the first such value substituted as the plugin result.
|
41
|
+
This ensures that only plugins which understand `Marker` instances for top-level arguments will encounter them.
|
42
|
+
"""
|
43
|
+
|
44
|
+
accept_lazy_markers: t.ClassVar[bool] = False
|
45
|
+
"""
|
46
|
+
When `False`, plugins will trigger a `MarkerError` exception when attempting to retrieve a `Marker` from a lazy container.
|
47
|
+
This ensures that only plugins which understand lazy retrieval of `Marker` instances will encounter them.
|
48
|
+
"""
|
32
49
|
|
33
|
-
def __init__(self, loader=None, templar=None, **kwargs):
|
50
|
+
def __init__(self, loader: _dataloader.DataLoader | None = None, templar: _template.Templar | None = None, **kwargs) -> None:
|
34
51
|
|
35
52
|
super(LookupBase, self).__init__()
|
36
53
|
|
@@ -72,7 +89,7 @@ class LookupBase(AnsiblePlugin):
|
|
72
89
|
return ret
|
73
90
|
|
74
91
|
@abstractmethod
|
75
|
-
def run(self, terms, variables
|
92
|
+
def run(self, terms, variables, **kwargs):
|
76
93
|
"""
|
77
94
|
When the playbook specifies a lookup, this method is run. The
|
78
95
|
arguments to the lookup become the arguments to this method. One
|
@@ -104,9 +121,9 @@ class LookupBase(AnsiblePlugin):
|
|
104
121
|
pass
|
105
122
|
|
106
123
|
def find_file_in_search_path(self, myvars, subdir, needle, ignore_missing=False):
|
107
|
-
|
124
|
+
"""
|
108
125
|
Return a file (needle) in the task's expected search path.
|
109
|
-
|
126
|
+
"""
|
110
127
|
|
111
128
|
if 'ansible_search_path' in myvars:
|
112
129
|
paths = myvars['ansible_search_path']
|