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
|
@@ -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']
|
ansible/plugins/lookup/config.py
CHANGED
|
@@ -83,32 +83,20 @@ _raw:
|
|
|
83
83
|
import ansible.plugins.loader as plugin_loader
|
|
84
84
|
|
|
85
85
|
from ansible import constants as C
|
|
86
|
-
from ansible.
|
|
87
|
-
from ansible.
|
|
88
|
-
from ansible.module_utils.six import string_types
|
|
86
|
+
from ansible.module_utils.common.sentinel import Sentinel
|
|
87
|
+
from ansible.errors import AnsibleError, AnsibleUndefinedConfigEntry
|
|
89
88
|
from ansible.plugins.lookup import LookupBase
|
|
90
|
-
from ansible.utils.sentinel import Sentinel
|
|
91
89
|
|
|
92
90
|
|
|
93
|
-
|
|
94
|
-
|
|
91
|
+
def _get_plugin_config(pname, ptype, config, variables):
|
|
92
|
+
# plugin creates settings on load, this is cached so not too expensive to redo
|
|
93
|
+
loader = getattr(plugin_loader, '%s_loader' % ptype)
|
|
94
|
+
p = loader.get(pname, class_only=True)
|
|
95
95
|
|
|
96
|
+
if p is None:
|
|
97
|
+
raise AnsibleError(f"Unable to load {ptype} plugin {pname!r}.")
|
|
96
98
|
|
|
97
|
-
|
|
98
|
-
try:
|
|
99
|
-
# plugin creates settings on load, this is cached so not too expensive to redo
|
|
100
|
-
loader = getattr(plugin_loader, '%s_loader' % ptype)
|
|
101
|
-
p = loader.get(pname, class_only=True)
|
|
102
|
-
if p is None:
|
|
103
|
-
raise AnsibleLookupError('Unable to load %s plugin "%s"' % (ptype, pname))
|
|
104
|
-
result, origin = C.config.get_config_value_and_origin(config, plugin_type=ptype, plugin_name=p._load_name, variables=variables)
|
|
105
|
-
except AnsibleLookupError:
|
|
106
|
-
raise
|
|
107
|
-
except AnsibleError as e:
|
|
108
|
-
msg = to_native(e)
|
|
109
|
-
if 'was not defined' in msg:
|
|
110
|
-
raise MissingSetting(msg, orig_exc=e)
|
|
111
|
-
raise e
|
|
99
|
+
result, origin = C.config.get_config_value_and_origin(config, plugin_type=ptype, plugin_name=p._load_name, variables=variables)
|
|
112
100
|
|
|
113
101
|
return result, origin
|
|
114
102
|
|
|
@@ -116,10 +104,11 @@ def _get_plugin_config(pname, ptype, config, variables):
|
|
|
116
104
|
def _get_global_config(config):
|
|
117
105
|
try:
|
|
118
106
|
result = getattr(C, config)
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
107
|
+
except AttributeError:
|
|
108
|
+
raise AnsibleUndefinedConfigEntry(f"Setting {config!r} does not exist.") from None
|
|
109
|
+
|
|
110
|
+
if callable(result):
|
|
111
|
+
raise ValueError(f"Invalid setting {config!r} attempted.")
|
|
123
112
|
|
|
124
113
|
return result
|
|
125
114
|
|
|
@@ -136,16 +125,13 @@ class LookupModule(LookupBase):
|
|
|
136
125
|
show_origin = self.get_option('show_origin')
|
|
137
126
|
|
|
138
127
|
if (ptype or pname) and not (ptype and pname):
|
|
139
|
-
raise
|
|
140
|
-
|
|
141
|
-
if not isinstance(missing, string_types) or missing not in ['error', 'warn', 'skip']:
|
|
142
|
-
raise AnsibleOptionsError('"on_missing" must be a string and one of "error", "warn" or "skip", not %s' % missing)
|
|
128
|
+
raise AnsibleError('Both plugin_type and plugin_name are required, cannot use one without the other.')
|
|
143
129
|
|
|
144
130
|
ret = []
|
|
145
131
|
|
|
146
132
|
for term in terms:
|
|
147
|
-
if not isinstance(term,
|
|
148
|
-
raise
|
|
133
|
+
if not isinstance(term, str):
|
|
134
|
+
raise AnsibleError(f'Invalid setting identifier, {term!r} is not a {str}, its a {type(term)}.')
|
|
149
135
|
|
|
150
136
|
result = Sentinel
|
|
151
137
|
origin = None
|
|
@@ -154,17 +140,17 @@ class LookupModule(LookupBase):
|
|
|
154
140
|
result, origin = _get_plugin_config(pname, ptype, term, variables)
|
|
155
141
|
else:
|
|
156
142
|
result = _get_global_config(term)
|
|
157
|
-
except
|
|
143
|
+
except AnsibleUndefinedConfigEntry:
|
|
158
144
|
if missing == 'error':
|
|
159
|
-
raise
|
|
145
|
+
raise
|
|
160
146
|
elif missing == 'warn':
|
|
161
|
-
self._display.warning(
|
|
147
|
+
self._display.warning(f"Skipping, did not find setting {term!r}.")
|
|
162
148
|
elif missing == 'skip':
|
|
163
149
|
pass # this is not needed, but added to have all 3 options stated
|
|
164
150
|
|
|
165
151
|
if result is not Sentinel:
|
|
166
152
|
if show_origin:
|
|
167
|
-
ret.append(
|
|
153
|
+
ret.append([result, origin])
|
|
168
154
|
else:
|
|
169
155
|
ret.append(result)
|
|
170
156
|
return ret
|
|
@@ -16,7 +16,8 @@ DOCUMENTATION = r"""
|
|
|
16
16
|
options:
|
|
17
17
|
col:
|
|
18
18
|
description: column to return (0 indexed).
|
|
19
|
-
default:
|
|
19
|
+
default: 1
|
|
20
|
+
type: int
|
|
20
21
|
keycol:
|
|
21
22
|
description: column to search in (0 indexed).
|
|
22
23
|
default: 0
|
|
@@ -102,76 +103,26 @@ RETURN = """
|
|
|
102
103
|
elements: str
|
|
103
104
|
"""
|
|
104
105
|
|
|
105
|
-
import codecs
|
|
106
106
|
import csv
|
|
107
107
|
|
|
108
108
|
from collections.abc import MutableSequence
|
|
109
109
|
|
|
110
|
-
from ansible.errors import AnsibleError
|
|
110
|
+
from ansible.errors import AnsibleError
|
|
111
111
|
from ansible.parsing.splitter import parse_kv
|
|
112
112
|
from ansible.plugins.lookup import LookupBase
|
|
113
|
-
from ansible.module_utils.six import PY2
|
|
114
|
-
from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
class CSVRecoder:
|
|
118
|
-
"""
|
|
119
|
-
Iterator that reads an encoded stream and encodes the input to UTF-8
|
|
120
|
-
"""
|
|
121
|
-
def __init__(self, f, encoding='utf-8'):
|
|
122
|
-
self.reader = codecs.getreader(encoding)(f)
|
|
123
|
-
|
|
124
|
-
def __iter__(self):
|
|
125
|
-
return self
|
|
126
|
-
|
|
127
|
-
def __next__(self):
|
|
128
|
-
return next(self.reader).encode("utf-8")
|
|
129
|
-
|
|
130
|
-
next = __next__ # For Python 2
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
class CSVReader:
|
|
134
|
-
"""
|
|
135
|
-
A CSV reader which will iterate over lines in the CSV file "f",
|
|
136
|
-
which is encoded in the given encoding.
|
|
137
|
-
"""
|
|
138
|
-
|
|
139
|
-
def __init__(self, f, dialect=csv.excel, encoding='utf-8', **kwds):
|
|
140
|
-
if PY2:
|
|
141
|
-
f = CSVRecoder(f, encoding)
|
|
142
|
-
else:
|
|
143
|
-
f = codecs.getreader(encoding)(f)
|
|
144
|
-
|
|
145
|
-
self.reader = csv.reader(f, dialect=dialect, **kwds)
|
|
146
|
-
|
|
147
|
-
def __next__(self):
|
|
148
|
-
row = next(self.reader)
|
|
149
|
-
return [to_text(s) for s in row]
|
|
150
|
-
|
|
151
|
-
next = __next__ # For Python 2
|
|
152
|
-
|
|
153
|
-
def __iter__(self):
|
|
154
|
-
return self
|
|
155
113
|
|
|
156
114
|
|
|
157
115
|
class LookupModule(LookupBase):
|
|
158
116
|
|
|
159
117
|
def read_csv(self, filename, key, delimiter, encoding='utf-8', dflt=None, col=1, keycol=0):
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
for row in creader:
|
|
166
|
-
if len(row) and row[keycol] == key:
|
|
167
|
-
return row[int(col)]
|
|
168
|
-
except Exception as e:
|
|
169
|
-
raise AnsibleError("csvfile: %s" % to_native(e))
|
|
118
|
+
with open(filename, encoding=encoding) as f:
|
|
119
|
+
for row in csv.reader(f, dialect=csv.excel, delimiter=delimiter):
|
|
120
|
+
if row and row[keycol] == key:
|
|
121
|
+
return row[col]
|
|
170
122
|
|
|
171
123
|
return dflt
|
|
172
124
|
|
|
173
125
|
def run(self, terms, variables=None, **kwargs):
|
|
174
|
-
|
|
175
126
|
ret = []
|
|
176
127
|
|
|
177
128
|
self.set_options(var_options=variables, direct=kwargs)
|
|
@@ -191,23 +142,19 @@ class LookupModule(LookupBase):
|
|
|
191
142
|
key = kv['_raw_params']
|
|
192
143
|
|
|
193
144
|
# parameters override per term using k/v
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
raise AnsibleAssertionError('%s is not a valid option' % name)
|
|
201
|
-
|
|
202
|
-
self._deprecate_inline_kv()
|
|
203
|
-
self.set_option(name, value)
|
|
204
|
-
reset_params = True
|
|
145
|
+
reset_params = False
|
|
146
|
+
for name, value in kv.items():
|
|
147
|
+
if name == '_raw_params':
|
|
148
|
+
continue
|
|
149
|
+
if name not in paramvals:
|
|
150
|
+
raise ValueError(f'{name!r} is not a valid option')
|
|
205
151
|
|
|
206
|
-
|
|
207
|
-
|
|
152
|
+
self._deprecate_inline_kv()
|
|
153
|
+
self.set_option(name, value)
|
|
154
|
+
reset_params = True
|
|
208
155
|
|
|
209
|
-
|
|
210
|
-
|
|
156
|
+
if reset_params:
|
|
157
|
+
paramvals = self.get_options()
|
|
211
158
|
|
|
212
159
|
# default is just placeholder for real tab
|
|
213
160
|
if paramvals['delimiter'] == 'TAB':
|
|
@@ -217,8 +164,7 @@ class LookupModule(LookupBase):
|
|
|
217
164
|
var = self.read_csv(lookupfile, key, paramvals['delimiter'], paramvals['encoding'], paramvals['default'], paramvals['col'], paramvals['keycol'])
|
|
218
165
|
if var is not None:
|
|
219
166
|
if isinstance(var, MutableSequence):
|
|
220
|
-
|
|
221
|
-
ret.append(v)
|
|
167
|
+
ret.extend(var)
|
|
222
168
|
else:
|
|
223
169
|
ret.append(var)
|
|
224
170
|
|
ansible/plugins/lookup/dict.py
CHANGED
|
@@ -61,16 +61,11 @@ from ansible.plugins.lookup import LookupBase
|
|
|
61
61
|
class LookupModule(LookupBase):
|
|
62
62
|
|
|
63
63
|
def run(self, terms, variables=None, **kwargs):
|
|
64
|
-
|
|
65
|
-
# NOTE: can remove if with_ is removed
|
|
66
|
-
if not isinstance(terms, list):
|
|
67
|
-
terms = [terms]
|
|
68
|
-
|
|
69
64
|
results = []
|
|
70
65
|
for term in terms:
|
|
71
66
|
# Expect any type of Mapping, notably hostvars
|
|
72
67
|
if not isinstance(term, Mapping):
|
|
73
|
-
raise AnsibleError("
|
|
68
|
+
raise AnsibleError(f"the 'dict' lookup plugin expects a dictionary, got '{term}' of type {type(term)})")
|
|
74
69
|
|
|
75
70
|
results.extend(self._flatten_hash_to_list(term))
|
|
76
71
|
return results
|
ansible/plugins/lookup/env.py
CHANGED
|
@@ -38,10 +38,6 @@ EXAMPLES = """
|
|
|
38
38
|
ansible.builtin.debug:
|
|
39
39
|
msg: "Hello {{ lookup('ansible.builtin.env', 'UNDEFINED_VARIABLE', default='World') }}"
|
|
40
40
|
|
|
41
|
-
- name: Fail if the variable is not defined by setting default value to 'Undefined'
|
|
42
|
-
ansible.builtin.debug:
|
|
43
|
-
msg: "Hello {{ lookup('ansible.builtin.env', 'UNDEFINED_VARIABLE', default=Undefined) }}"
|
|
44
|
-
|
|
45
41
|
- name: Fail if the variable is not defined by setting default value to 'undef()'
|
|
46
42
|
ansible.builtin.debug:
|
|
47
43
|
msg: "Hello {{ lookup('ansible.builtin.env', 'UNDEFINED_VARIABLE', default=undef()) }}"
|
|
@@ -56,23 +52,30 @@ RETURN = """
|
|
|
56
52
|
|
|
57
53
|
import os
|
|
58
54
|
|
|
59
|
-
from jinja2.runtime import Undefined
|
|
60
55
|
|
|
61
|
-
from ansible.errors import AnsibleUndefinedVariable
|
|
62
56
|
from ansible.plugins.lookup import LookupBase
|
|
57
|
+
from ansible._internal._templating._jinja_bits import _undef, _DEFAULT_UNDEF
|
|
58
|
+
from ansible._internal._datatag._tags import Origin
|
|
63
59
|
|
|
64
60
|
|
|
65
61
|
class LookupModule(LookupBase):
|
|
66
|
-
|
|
62
|
+
accept_args_markers = True # the `default` arg can accept undefined values
|
|
67
63
|
|
|
64
|
+
def run(self, terms, variables=None, **kwargs):
|
|
68
65
|
self.set_options(var_options=variables, direct=kwargs)
|
|
69
66
|
|
|
70
67
|
ret = []
|
|
71
68
|
d = self.get_option('default')
|
|
69
|
+
|
|
72
70
|
for term in terms:
|
|
73
71
|
var = term.split()[0]
|
|
74
72
|
val = os.environ.get(var, d)
|
|
75
|
-
|
|
76
|
-
|
|
73
|
+
|
|
74
|
+
if val is _DEFAULT_UNDEF:
|
|
75
|
+
val = _undef(f'The environment variable {var!r} is not set.')
|
|
76
|
+
else:
|
|
77
|
+
val = Origin(description=f"<environment variable {var!r}>").try_tag(val)
|
|
78
|
+
|
|
77
79
|
ret.append(val)
|
|
80
|
+
|
|
78
81
|
return ret
|
ansible/plugins/lookup/file.py
CHANGED
|
@@ -25,7 +25,6 @@ DOCUMENTATION = """
|
|
|
25
25
|
required: False
|
|
26
26
|
default: False
|
|
27
27
|
notes:
|
|
28
|
-
- if read in variable context, the file can be interpreted as YAML if the content is valid to the parser.
|
|
29
28
|
- this lookup does not understand 'globbing', use the fileglob lookup instead.
|
|
30
29
|
seealso:
|
|
31
30
|
- ref: playbook_task_paths
|
|
@@ -52,9 +51,8 @@ RETURN = """
|
|
|
52
51
|
elements: str
|
|
53
52
|
"""
|
|
54
53
|
|
|
55
|
-
from ansible.errors import AnsibleError
|
|
54
|
+
from ansible.errors import AnsibleError
|
|
56
55
|
from ansible.plugins.lookup import LookupBase
|
|
57
|
-
from ansible.module_utils.common.text.converters import to_text
|
|
58
56
|
from ansible.utils.display import Display
|
|
59
57
|
|
|
60
58
|
display = Display()
|
|
@@ -74,8 +72,7 @@ class LookupModule(LookupBase):
|
|
|
74
72
|
lookupfile = self.find_file_in_search_path(variables, 'files', term, ignore_missing=True)
|
|
75
73
|
display.vvvv(u"File lookup using %s as file" % lookupfile)
|
|
76
74
|
if lookupfile:
|
|
77
|
-
|
|
78
|
-
contents = to_text(b_contents, errors='surrogate_or_strict')
|
|
75
|
+
contents = self._loader.get_text_file_contents(lookupfile)
|
|
79
76
|
if self.get_option('lstrip'):
|
|
80
77
|
contents = contents.lstrip()
|
|
81
78
|
if self.get_option('rstrip'):
|
|
@@ -83,8 +80,8 @@ class LookupModule(LookupBase):
|
|
|
83
80
|
ret.append(contents)
|
|
84
81
|
else:
|
|
85
82
|
# TODO: only add search info if abs path?
|
|
86
|
-
raise
|
|
87
|
-
except AnsibleError as
|
|
88
|
-
raise
|
|
83
|
+
raise AnsibleError("File not found. Use -vvvvv to see paths searched.")
|
|
84
|
+
except AnsibleError as ex:
|
|
85
|
+
raise AnsibleError(f"Unable to access the file {term!r}.") from ex
|
|
89
86
|
|
|
90
87
|
return ret
|
|
@@ -40,15 +40,16 @@ DOCUMENTATION = """
|
|
|
40
40
|
- When used as a template via C(lookup) or C(query), setting O(skip=True) will *not* cause the task to skip.
|
|
41
41
|
Tasks must handle the empty list return from the template.
|
|
42
42
|
- When V(False) and C(lookup) or C(query) specifies O(ignore:errors='ignore') all errors (including no file found,
|
|
43
|
-
but potentially others) return
|
|
43
|
+
but potentially others) return V(None) or an empty list respectively.
|
|
44
44
|
- When V(True) and C(lookup) or C(query) specifies O(ignore:errors='ignore'), no file found will return an empty
|
|
45
|
-
list and other potential errors return
|
|
45
|
+
list and other potential errors return V(None) or empty list depending on the template call
|
|
46
46
|
(in other words return values of C(lookup) vs C(query)).
|
|
47
47
|
seealso:
|
|
48
48
|
- ref: playbook_task_paths
|
|
49
49
|
description: Search paths used for relative paths/files.
|
|
50
50
|
"""
|
|
51
51
|
|
|
52
|
+
|
|
52
53
|
EXAMPLES = """
|
|
53
54
|
- name: Set _found_file to the first existing file, raising an error if a file is not found
|
|
54
55
|
ansible.builtin.set_fact:
|
|
@@ -137,70 +138,77 @@ RETURN = """
|
|
|
137
138
|
type: list
|
|
138
139
|
elements: path
|
|
139
140
|
"""
|
|
140
|
-
import os
|
|
141
|
-
|
|
142
|
-
from collections.abc import Mapping, Sequence
|
|
143
141
|
|
|
144
|
-
|
|
142
|
+
import collections.abc as c
|
|
143
|
+
import os
|
|
144
|
+
import re
|
|
145
|
+
import typing as t
|
|
145
146
|
|
|
146
|
-
from ansible.
|
|
147
|
-
from ansible.
|
|
147
|
+
from ansible._internal import _task
|
|
148
|
+
from ansible.errors import AnsibleError
|
|
148
149
|
from ansible.plugins.lookup import LookupBase
|
|
150
|
+
from ansible._internal._templating import _jinja_common
|
|
151
|
+
from ansible._internal._templating import _jinja_plugins
|
|
152
|
+
from ansible import template as _template
|
|
149
153
|
from ansible.utils.path import unfrackpath
|
|
154
|
+
from ansible.utils.display import Display
|
|
155
|
+
from ansible.module_utils.datatag import native_type_name
|
|
156
|
+
|
|
150
157
|
|
|
158
|
+
def _split_on(target: str, terms: str | list[str], splitters: str) -> list[str]:
|
|
159
|
+
termlist: list[str] = []
|
|
151
160
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
v = ''
|
|
155
|
-
for c in value:
|
|
156
|
-
if c in chars:
|
|
157
|
-
yield v
|
|
158
|
-
v = ''
|
|
159
|
-
continue
|
|
160
|
-
v += c
|
|
161
|
-
yield v
|
|
161
|
+
if isinstance(terms, str):
|
|
162
|
+
split_terms = re.split(r'[%s]' % ''.join(map(re.escape, splitters)), terms)
|
|
162
163
|
|
|
164
|
+
if split_terms == [terms]:
|
|
165
|
+
termlist = [terms]
|
|
166
|
+
else:
|
|
167
|
+
Display().deprecated(
|
|
168
|
+
msg=f'Automatic splitting of {target} on {splitters!r} is deprecated.',
|
|
169
|
+
help_text=f'Provide a list of paths for {target} instead.',
|
|
170
|
+
version='2.23',
|
|
171
|
+
obj=terms,
|
|
172
|
+
)
|
|
163
173
|
|
|
164
|
-
|
|
165
|
-
termlist = []
|
|
166
|
-
if isinstance(terms, string_types):
|
|
167
|
-
termlist = list(_splitter(terms, spliters))
|
|
174
|
+
termlist = split_terms
|
|
168
175
|
else:
|
|
169
176
|
# added since options will already listify
|
|
170
|
-
for
|
|
171
|
-
termlist.extend(_split_on(
|
|
177
|
+
for term in terms:
|
|
178
|
+
termlist.extend(_split_on(target, term, splitters))
|
|
179
|
+
|
|
172
180
|
return termlist
|
|
173
181
|
|
|
174
182
|
|
|
175
183
|
class LookupModule(LookupBase):
|
|
184
|
+
accept_args_markers = True # terms are allowed to be undefined
|
|
185
|
+
accept_lazy_markers = True # terms are allowed to be undefined
|
|
176
186
|
|
|
177
|
-
def _process_terms(self, terms, variables,
|
|
187
|
+
def _process_terms(self, terms: c.Sequence, variables: dict[str, t.Any]) -> list[str]:
|
|
178
188
|
|
|
179
189
|
total_search = []
|
|
180
|
-
skip = False
|
|
181
190
|
|
|
182
191
|
# can use a dict instead of list item to pass inline config
|
|
183
192
|
for term in terms:
|
|
184
|
-
if isinstance(term, Mapping):
|
|
193
|
+
if isinstance(term, c.Mapping):
|
|
185
194
|
self.set_options(var_options=variables, direct=term)
|
|
186
195
|
files = self.get_option('files')
|
|
187
|
-
|
|
196
|
+
files_description = "the 'files' option"
|
|
197
|
+
elif isinstance(term, str):
|
|
188
198
|
files = [term]
|
|
189
|
-
|
|
190
|
-
|
|
199
|
+
files_description = "files"
|
|
200
|
+
elif isinstance(term, c.Sequence):
|
|
201
|
+
partial = self._process_terms(term, variables)
|
|
191
202
|
total_search.extend(partial)
|
|
192
203
|
continue
|
|
193
204
|
else:
|
|
194
|
-
raise
|
|
205
|
+
raise AnsibleError(f"Invalid term supplied. A string, dict or list is required, not {native_type_name(term)!r}).")
|
|
195
206
|
|
|
196
207
|
paths = self.get_option('paths')
|
|
197
208
|
|
|
198
|
-
# NOTE: this is used as 'global' but can be set many times?!?!?
|
|
199
|
-
skip = self.get_option('skip')
|
|
200
|
-
|
|
201
209
|
# magic extra splitting to create lists
|
|
202
|
-
filelist = _split_on(files, ',;')
|
|
203
|
-
pathlist = _split_on(paths, ',:;')
|
|
210
|
+
filelist = _split_on(files_description, files, ',;')
|
|
211
|
+
pathlist = _split_on('the "paths" option', paths, ',:;')
|
|
204
212
|
|
|
205
213
|
# create search structure
|
|
206
214
|
if pathlist:
|
|
@@ -208,40 +216,46 @@ class LookupModule(LookupBase):
|
|
|
208
216
|
for fn in filelist:
|
|
209
217
|
f = os.path.join(path, fn)
|
|
210
218
|
total_search.append(f)
|
|
211
|
-
|
|
219
|
+
else:
|
|
212
220
|
# NOTE: this is now 'extend', previously it would clobber all options, but we deemed that a bug
|
|
213
221
|
total_search.extend(filelist)
|
|
214
|
-
else:
|
|
215
|
-
total_search.append(term)
|
|
216
222
|
|
|
217
|
-
return total_search
|
|
223
|
+
return total_search
|
|
224
|
+
|
|
225
|
+
def run(self, terms: list, variables=None, **kwargs):
|
|
226
|
+
if (first_marker := _template.get_first_marker_arg((), kwargs)) is not None:
|
|
227
|
+
first_marker.trip()
|
|
218
228
|
|
|
219
|
-
|
|
229
|
+
if _jinja_plugins._LookupContext.current().invoked_as_with:
|
|
230
|
+
# we're being invoked by TaskExecutor.get_loop_items(), special backwards compatibility behavior
|
|
231
|
+
terms = _recurse_terms(terms, omit_undefined=True) # recursively drop undefined values from terms for backwards compatibility
|
|
232
|
+
|
|
233
|
+
# invoked_as_with shouldn't be possible outside a TaskContext
|
|
234
|
+
te_action = _task.TaskContext.current().task.action # FIXME: this value has not been templated, it should be (historical problem)...
|
|
235
|
+
|
|
236
|
+
# based on the presence of `var`/`template`/`file` in the enclosing task action name, choose a subdir to search
|
|
237
|
+
for subdir in ['template', 'var', 'file']:
|
|
238
|
+
if subdir in te_action:
|
|
239
|
+
break
|
|
240
|
+
|
|
241
|
+
subdir += "s" # convert to the matching directory name
|
|
242
|
+
else:
|
|
243
|
+
terms = _recurse_terms(terms, omit_undefined=False) # undefined values are only omitted when invoked using `with`
|
|
244
|
+
|
|
245
|
+
subdir = None
|
|
220
246
|
|
|
221
247
|
self.set_options(var_options=variables, direct=kwargs)
|
|
222
248
|
|
|
223
249
|
if not terms:
|
|
224
250
|
terms = self.get_option('files')
|
|
225
251
|
|
|
226
|
-
total_search
|
|
252
|
+
total_search = self._process_terms(terms, variables)
|
|
227
253
|
|
|
228
254
|
# NOTE: during refactor noticed that the 'using a dict' as term
|
|
229
255
|
# is designed to only work with 'one' otherwise inconsistencies will appear.
|
|
230
256
|
# see other notes below.
|
|
231
257
|
|
|
232
|
-
# actually search
|
|
233
|
-
subdir = getattr(self, '_subdir', 'files')
|
|
234
|
-
|
|
235
|
-
path = None
|
|
236
258
|
for fn in total_search:
|
|
237
|
-
|
|
238
|
-
try:
|
|
239
|
-
fn = self._templar.template(fn)
|
|
240
|
-
except (AnsibleUndefinedVariable, UndefinedError):
|
|
241
|
-
# NOTE: backwards compat ff behaviour is to ignore errors when vars are undefined.
|
|
242
|
-
# moved here from task_executor.
|
|
243
|
-
continue
|
|
244
|
-
|
|
245
259
|
# get subdir if set by task executor, default to files otherwise
|
|
246
260
|
path = self.find_file_in_search_path(variables, subdir, fn, ignore_missing=True)
|
|
247
261
|
|
|
@@ -249,8 +263,26 @@ class LookupModule(LookupBase):
|
|
|
249
263
|
if path is not None:
|
|
250
264
|
return [unfrackpath(path, follow=False)]
|
|
251
265
|
|
|
266
|
+
skip = self.get_option('skip')
|
|
267
|
+
|
|
252
268
|
# if we get here, no file was found
|
|
253
269
|
if skip:
|
|
254
270
|
# NOTE: global skip won't matter, only last 'skip' value in dict term
|
|
255
271
|
return []
|
|
256
|
-
|
|
272
|
+
|
|
273
|
+
raise AnsibleError("No file was found when using first_found.")
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
def _recurse_terms(o: t.Any, omit_undefined: bool) -> t.Any:
|
|
277
|
+
"""Recurse through supported container types, optionally omitting undefined markers and tripping all remaining markers, returning the result."""
|
|
278
|
+
match o:
|
|
279
|
+
case dict():
|
|
280
|
+
return {k: _recurse_terms(v, omit_undefined) for k, v in o.items() if not (omit_undefined and isinstance(v, _jinja_common.UndefinedMarker))}
|
|
281
|
+
case list():
|
|
282
|
+
return [_recurse_terms(v, omit_undefined) for v in o if not (omit_undefined and isinstance(v, _jinja_common.UndefinedMarker))]
|
|
283
|
+
case tuple():
|
|
284
|
+
return tuple(_recurse_terms(v, omit_undefined) for v in o if not (omit_undefined and isinstance(v, _jinja_common.UndefinedMarker)))
|
|
285
|
+
case _jinja_common.Marker():
|
|
286
|
+
o.trip()
|
|
287
|
+
case _:
|
|
288
|
+
return o
|
|
@@ -33,19 +33,10 @@ RETURN = """
|
|
|
33
33
|
elements: list
|
|
34
34
|
"""
|
|
35
35
|
|
|
36
|
-
from ansible.errors import AnsibleError
|
|
37
36
|
from ansible.plugins.lookup import LookupBase
|
|
38
37
|
|
|
39
38
|
|
|
40
39
|
class LookupModule(LookupBase):
|
|
41
|
-
|
|
42
|
-
def __init__(self, basedir=None, **kwargs):
|
|
43
|
-
self.basedir = basedir
|
|
44
|
-
|
|
45
|
-
def run(self, terms, variables, **kwargs):
|
|
46
|
-
|
|
47
|
-
if not isinstance(terms, list):
|
|
48
|
-
raise AnsibleError("with_indexed_items expects a list")
|
|
49
|
-
|
|
40
|
+
def run(self, terms, variables=None, **kwargs):
|
|
50
41
|
items = self._flatten(terms)
|
|
51
42
|
return list(zip(range(len(items)), items))
|