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/playbook/task.py
CHANGED
@@ -17,13 +17,18 @@
|
|
17
17
|
|
18
18
|
from __future__ import annotations
|
19
19
|
|
20
|
+
import typing as t
|
21
|
+
|
20
22
|
from ansible import constants as C
|
21
|
-
from ansible.
|
23
|
+
from ansible.module_utils.common.sentinel import Sentinel
|
24
|
+
from ansible.errors import AnsibleError, AnsibleParserError, AnsibleUndefinedVariable, AnsibleAssertionError, AnsibleValueOmittedError
|
25
|
+
from ansible.executor.module_common import _get_action_arg_defaults
|
22
26
|
from ansible.module_utils.common.text.converters import to_native
|
27
|
+
from ansible.module_utils._internal._datatag import AnsibleTagHelper
|
23
28
|
from ansible.module_utils.six import string_types
|
24
|
-
from ansible.parsing.mod_args import ModuleArgsParser
|
25
|
-
from ansible.
|
26
|
-
from ansible.plugins.loader import lookup_loader
|
29
|
+
from ansible.parsing.mod_args import ModuleArgsParser, RAW_PARAM_MODULES
|
30
|
+
from ansible.plugins.action import ActionBase
|
31
|
+
from ansible.plugins.loader import action_loader, module_loader, lookup_loader
|
27
32
|
from ansible.playbook.attribute import NonInheritableFieldAttribute
|
28
33
|
from ansible.playbook.base import Base
|
29
34
|
from ansible.playbook.block import Block
|
@@ -34,10 +39,14 @@ from ansible.playbook.loop_control import LoopControl
|
|
34
39
|
from ansible.playbook.notifiable import Notifiable
|
35
40
|
from ansible.playbook.role import Role
|
36
41
|
from ansible.playbook.taggable import Taggable
|
42
|
+
from ansible._internal import _task
|
43
|
+
from ansible._internal._templating import _marker_behaviors
|
44
|
+
from ansible._internal._templating._jinja_bits import is_possibly_all_template
|
45
|
+
from ansible._internal._templating._engine import TemplateEngine, TemplateOptions
|
37
46
|
from ansible.utils.collection_loader import AnsibleCollectionConfig
|
38
47
|
from ansible.utils.display import Display
|
39
|
-
|
40
|
-
from ansible.utils.vars import
|
48
|
+
|
49
|
+
from ansible.utils.vars import validate_variable_name
|
41
50
|
|
42
51
|
__all__ = ['Task']
|
43
52
|
|
@@ -67,8 +76,8 @@ class Task(Base, Conditional, Taggable, CollectionSearch, Notifiable, Delegatabl
|
|
67
76
|
# inheritance is only triggered if the 'current value' is Sentinel,
|
68
77
|
# default can be set at play/top level object and inheritance will take it's course.
|
69
78
|
|
70
|
-
args = NonInheritableFieldAttribute(isa='dict', default=dict)
|
71
|
-
action = NonInheritableFieldAttribute(isa='string')
|
79
|
+
args = t.cast(dict, NonInheritableFieldAttribute(isa='dict', default=dict))
|
80
|
+
action = t.cast(str, NonInheritableFieldAttribute(isa='string'))
|
72
81
|
|
73
82
|
async_val = NonInheritableFieldAttribute(isa='int', default=0, alias='async')
|
74
83
|
changed_when = NonInheritableFieldAttribute(isa='list', default=list)
|
@@ -84,13 +93,13 @@ class Task(Base, Conditional, Taggable, CollectionSearch, Notifiable, Delegatabl
|
|
84
93
|
# deprecated, used to be loop and loop_args but loop has been repurposed
|
85
94
|
loop_with = NonInheritableFieldAttribute(isa='string', private=True)
|
86
95
|
|
87
|
-
def __init__(self, block=None, role=None, task_include=None):
|
88
|
-
|
96
|
+
def __init__(self, block=None, role=None, task_include=None) -> None:
|
97
|
+
""" constructors a task, without the Task.load classmethod, it will be pretty blank """
|
89
98
|
|
90
99
|
self._role = role
|
91
100
|
self._parent = None
|
92
101
|
self.implicit = False
|
93
|
-
self.resolved_action = None
|
102
|
+
self.resolved_action: str | None = None
|
94
103
|
|
95
104
|
if task_include:
|
96
105
|
self._parent = task_include
|
@@ -100,7 +109,7 @@ class Task(Base, Conditional, Taggable, CollectionSearch, Notifiable, Delegatabl
|
|
100
109
|
super(Task, self).__init__()
|
101
110
|
|
102
111
|
def get_name(self, include_role_fqcn=True):
|
103
|
-
|
112
|
+
""" return the name of the task """
|
104
113
|
|
105
114
|
if self._role:
|
106
115
|
role_name = self._role.get_name(include_role_fqcn=include_role_fqcn)
|
@@ -131,18 +140,85 @@ class Task(Base, Conditional, Taggable, CollectionSearch, Notifiable, Delegatabl
|
|
131
140
|
|
132
141
|
@staticmethod
|
133
142
|
def load(data, block=None, role=None, task_include=None, variable_manager=None, loader=None):
|
134
|
-
|
135
|
-
return
|
143
|
+
task = Task(block=block, role=role, task_include=task_include)
|
144
|
+
return task.load_data(data, variable_manager=variable_manager, loader=loader)
|
136
145
|
|
137
|
-
def
|
138
|
-
|
146
|
+
def _post_validate_module_defaults(self, attr: str, value: t.Any, templar: TemplateEngine) -> t.Any:
|
147
|
+
"""Override module_defaults post validation to disable templating, which is handled by args post validation."""
|
148
|
+
return value
|
149
|
+
|
150
|
+
def _post_validate_args(self, attr: str, value: t.Any, templar: TemplateEngine) -> dict[str, t.Any]:
|
151
|
+
try:
|
152
|
+
self.action = templar.template(self.action)
|
153
|
+
except AnsibleValueOmittedError:
|
154
|
+
# some strategies may trigger this error when templating task.action, but backstop here if not
|
155
|
+
raise AnsibleParserError("Omit is not valid for the `action` keyword.", obj=self.action) from None
|
156
|
+
|
157
|
+
action_context = action_loader.get_with_context(self.action, collection_list=self.collections, class_only=True)
|
158
|
+
|
159
|
+
if not action_context.plugin_load_context.resolved:
|
160
|
+
module_or_action_context = module_loader.find_plugin_with_context(self.action, collection_list=self.collections)
|
161
|
+
|
162
|
+
if not module_or_action_context.resolved:
|
163
|
+
raise AnsibleError(f"Cannot resolve {self.action!r} to an action or module.", obj=self.action)
|
164
|
+
|
165
|
+
action_context = action_loader.get_with_context('ansible.legacy.normal', collection_list=self.collections, class_only=True)
|
166
|
+
else:
|
167
|
+
module_or_action_context = action_context.plugin_load_context
|
168
|
+
|
169
|
+
self.resolved_action = module_or_action_context.resolved_fqcn
|
170
|
+
|
171
|
+
action_type: type[ActionBase] = action_context.object
|
172
|
+
|
173
|
+
vp = value.pop('_variable_params', None)
|
174
|
+
|
175
|
+
supports_raw_params = action_type.supports_raw_params or module_or_action_context.resolved_fqcn in RAW_PARAM_MODULES
|
176
|
+
|
177
|
+
if supports_raw_params:
|
178
|
+
raw_params_to_finalize = None
|
179
|
+
else:
|
180
|
+
raw_params_to_finalize = value.pop('_raw_params', None) # always str or None
|
181
|
+
|
182
|
+
# TaskArgsFinalizer performs more thorough type checking, but this provides a friendlier error message for a subset of detected cases.
|
183
|
+
if raw_params_to_finalize and not is_possibly_all_template(raw_params_to_finalize):
|
184
|
+
raise AnsibleError(f'Action {module_or_action_context.resolved_fqcn!r} does not support raw params.', obj=self.action)
|
185
|
+
|
186
|
+
args_finalizer = _task.TaskArgsFinalizer(
|
187
|
+
_get_action_arg_defaults(module_or_action_context.resolved_fqcn, self, templar),
|
188
|
+
vp,
|
189
|
+
raw_params_to_finalize,
|
190
|
+
value,
|
191
|
+
templar=templar,
|
192
|
+
)
|
193
|
+
|
194
|
+
try:
|
195
|
+
with action_type.get_finalize_task_args_context() as finalize_context:
|
196
|
+
args = args_finalizer.finalize(action_type.finalize_task_arg, context=finalize_context)
|
197
|
+
except Exception as ex:
|
198
|
+
raise AnsibleError(f'Finalization of task args for {module_or_action_context.resolved_fqcn!r} failed.', obj=self.action) from ex
|
199
|
+
|
200
|
+
if self._origin:
|
201
|
+
args = self._origin.tag(args)
|
202
|
+
|
203
|
+
return args
|
204
|
+
|
205
|
+
def _get_meta(self) -> str | None:
|
206
|
+
# FUTURE: validate meta and return an enum instead of a str
|
207
|
+
# meta currently does not support being templated, so we can cheat
|
139
208
|
if self.action in C._ACTION_META:
|
140
|
-
return
|
209
|
+
return self.args.get('_raw_params')
|
210
|
+
|
211
|
+
return None
|
212
|
+
|
213
|
+
def __repr__(self):
|
214
|
+
""" returns a human-readable representation of the task """
|
215
|
+
if meta := self._get_meta():
|
216
|
+
return f"TASK: meta ({meta})"
|
141
217
|
else:
|
142
218
|
return "TASK: %s" % self.get_name()
|
143
219
|
|
144
220
|
def _preprocess_with_loop(self, ds, new_ds, k, v):
|
145
|
-
|
221
|
+
""" take a lookup plugin name and store it correctly """
|
146
222
|
|
147
223
|
loop_name = k.removeprefix("with_")
|
148
224
|
if new_ds.get('loop') is not None or new_ds.get('loop_with') is not None:
|
@@ -155,20 +231,17 @@ class Task(Base, Conditional, Taggable, CollectionSearch, Notifiable, Delegatabl
|
|
155
231
|
# version="2.10", collection_name='ansible.builtin')
|
156
232
|
|
157
233
|
def preprocess_data(self, ds):
|
158
|
-
|
234
|
+
"""
|
159
235
|
tasks are especially complex arguments so need pre-processing.
|
160
236
|
keep it short.
|
161
|
-
|
237
|
+
"""
|
162
238
|
|
163
239
|
if not isinstance(ds, dict):
|
164
240
|
raise AnsibleAssertionError('ds (%s) should be a dict but was a %s' % (ds, type(ds)))
|
165
241
|
|
166
|
-
# the new, cleaned datastructure, which will have legacy
|
167
|
-
#
|
168
|
-
|
169
|
-
new_ds = AnsibleMapping()
|
170
|
-
if isinstance(ds, AnsibleBaseYAMLObject):
|
171
|
-
new_ds.ansible_pos = ds.ansible_pos
|
242
|
+
# the new, cleaned datastructure, which will have legacy items reduced to a standard structure suitable for the
|
243
|
+
# attributes of the task class; copy any tagged data to preserve things like origin
|
244
|
+
new_ds = AnsibleTagHelper.tag_copy(ds, {})
|
172
245
|
|
173
246
|
# since this affects the task action parsing, we have to resolve in preprocess instead of in typical validator
|
174
247
|
default_collection = AnsibleCollectionConfig.default_collection
|
@@ -201,26 +274,13 @@ class Task(Base, Conditional, Taggable, CollectionSearch, Notifiable, Delegatabl
|
|
201
274
|
args_parser = ModuleArgsParser(task_ds=ds, collection_list=collections_list)
|
202
275
|
try:
|
203
276
|
(action, args, delegate_to) = args_parser.parse()
|
204
|
-
except AnsibleParserError as
|
277
|
+
except AnsibleParserError as ex:
|
205
278
|
# if the raises exception was created with obj=ds args, then it includes the detail
|
206
279
|
# so we dont need to add it so we can just re raise.
|
207
|
-
if
|
280
|
+
if ex.obj:
|
208
281
|
raise
|
209
282
|
# But if it wasn't, we can add the yaml object now to get more detail
|
210
|
-
raise AnsibleParserError(
|
211
|
-
else:
|
212
|
-
# Set the resolved action plugin (or if it does not exist, module) for callbacks.
|
213
|
-
self.resolved_action = args_parser.resolved_action
|
214
|
-
|
215
|
-
# the command/shell/script modules used to support the `cmd` arg,
|
216
|
-
# which corresponds to what we now call _raw_params, so move that
|
217
|
-
# value over to _raw_params (assuming it is empty)
|
218
|
-
if action in C._ACTION_HAS_CMD:
|
219
|
-
if 'cmd' in args:
|
220
|
-
if args.get('_raw_params', '') != '':
|
221
|
-
raise AnsibleError("The 'cmd' argument cannot be used when other raw parameters are specified."
|
222
|
-
" Please put everything in one or the other place.", obj=ds)
|
223
|
-
args['_raw_params'] = args.pop('cmd')
|
283
|
+
raise AnsibleParserError("Error parsing task arguments.", obj=ds) from ex
|
224
284
|
|
225
285
|
new_ds['action'] = action
|
226
286
|
new_ds['args'] = args
|
@@ -276,114 +336,99 @@ class Task(Base, Conditional, Taggable, CollectionSearch, Notifiable, Delegatabl
|
|
276
336
|
setattr(self, name, [value])
|
277
337
|
|
278
338
|
def _validate_register(self, attr, name, value):
|
279
|
-
if value is not None
|
280
|
-
|
339
|
+
if value is not None:
|
340
|
+
try:
|
341
|
+
validate_variable_name(value)
|
342
|
+
except Exception as ex:
|
343
|
+
raise AnsibleParserError("Invalid 'register' specified.", obj=value) from ex
|
281
344
|
|
282
345
|
def post_validate(self, templar):
|
283
|
-
|
346
|
+
"""
|
284
347
|
Override of base class post_validate, to also do final validation on
|
285
348
|
the block and task include (if any) to which this task belongs.
|
286
|
-
|
349
|
+
"""
|
287
350
|
|
288
351
|
if self._parent:
|
289
352
|
self._parent.post_validate(templar)
|
290
353
|
|
291
|
-
if AnsibleCollectionConfig.default_collection:
|
292
|
-
pass
|
293
|
-
|
294
354
|
super(Task, self).post_validate(templar)
|
295
355
|
|
296
|
-
def _post_validate_args(self, attr, value, templar):
|
297
|
-
# smuggle an untemplated copy of the task args for actions that need more control over the templating of their
|
298
|
-
# input (eg, debug's var/msg, assert's "that" conditional expressions)
|
299
|
-
self.untemplated_args = value
|
300
|
-
|
301
|
-
# now recursively template the args dict
|
302
|
-
args = templar.template(value)
|
303
|
-
|
304
|
-
# FIXME: could we just nuke this entirely and/or wrap it up in ModuleArgsParser or something?
|
305
|
-
if '_variable_params' in args:
|
306
|
-
variable_params = args.pop('_variable_params')
|
307
|
-
if isinstance(variable_params, dict):
|
308
|
-
if C.INJECT_FACTS_AS_VARS:
|
309
|
-
display.warning("Using a variable for a task's 'args' is unsafe in some situations "
|
310
|
-
"(see https://docs.ansible.com/ansible/devel/reference_appendices/faq.html#argsplat-unsafe)")
|
311
|
-
variable_params.update(args)
|
312
|
-
args = variable_params
|
313
|
-
else:
|
314
|
-
# if we didn't get a dict, it means there's garbage remaining after k=v parsing, just give up
|
315
|
-
# see https://github.com/ansible/ansible/issues/79862
|
316
|
-
raise AnsibleError(f"invalid or malformed argument: '{variable_params}'")
|
317
|
-
|
318
|
-
return args
|
319
|
-
|
320
356
|
def _post_validate_loop(self, attr, value, templar):
|
321
|
-
|
357
|
+
"""
|
322
358
|
Override post validation for the loop field, which is templated
|
323
359
|
specially in the TaskExecutor class when evaluating loops.
|
324
|
-
|
360
|
+
"""
|
325
361
|
return value
|
326
362
|
|
363
|
+
def _post_validate_name(self, attr, value, templar):
|
364
|
+
"""
|
365
|
+
Override post-validation behavior for `name` to be best-effort for the vars available.
|
366
|
+
Direct access via `post_validate_attribute` writes the value back to provide a stable value.
|
367
|
+
This value is individually post-validated early by strategies for the benefit of callbacks.
|
368
|
+
"""
|
369
|
+
with _marker_behaviors.ReplacingMarkerBehavior.warning_context() as replacing_behavior:
|
370
|
+
self.name = templar.extend(marker_behavior=replacing_behavior).template(value, options=TemplateOptions(value_for_omit=None))
|
371
|
+
|
372
|
+
return self.name
|
373
|
+
|
327
374
|
def _post_validate_environment(self, attr, value, templar):
|
328
|
-
|
375
|
+
"""
|
329
376
|
Override post validation of vars on the play, as we don't want to
|
330
377
|
template these too early.
|
331
|
-
|
378
|
+
"""
|
332
379
|
env = {}
|
333
|
-
if value is not None:
|
334
380
|
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
else:
|
355
|
-
display.warning("could not parse environment value, skipping: %s" % value)
|
356
|
-
|
357
|
-
elif isinstance(value, dict):
|
358
|
-
# should not really happen
|
359
|
-
env = dict()
|
360
|
-
for env_item in value:
|
361
|
-
_parse_env_kv(env_item, value[env_item])
|
381
|
+
# FUTURE: kill this with fire
|
382
|
+
def _parse_env_kv(k, v):
|
383
|
+
try:
|
384
|
+
env[k] = templar.template(v)
|
385
|
+
except AnsibleValueOmittedError:
|
386
|
+
# skip this value
|
387
|
+
return
|
388
|
+
except AnsibleUndefinedVariable as e:
|
389
|
+
error = to_native(e)
|
390
|
+
if self.action in C._ACTION_FACT_GATHERING and 'ansible_facts.env' in error or 'ansible_env' in error:
|
391
|
+
# ignore as fact gathering is required for 'env' facts
|
392
|
+
return
|
393
|
+
raise
|
394
|
+
|
395
|
+
# NB: the environment FieldAttribute definition ensures that value is always a list
|
396
|
+
for env_item in value:
|
397
|
+
if isinstance(env_item, dict):
|
398
|
+
for k in env_item:
|
399
|
+
_parse_env_kv(k, env_item[k])
|
362
400
|
else:
|
363
|
-
|
364
|
-
|
401
|
+
try:
|
402
|
+
isdict = templar.template(env_item)
|
403
|
+
except AnsibleValueOmittedError:
|
404
|
+
continue
|
405
|
+
|
406
|
+
if isinstance(isdict, dict):
|
407
|
+
env |= isdict
|
408
|
+
else:
|
409
|
+
display.warning("could not parse environment value, skipping: %s" % value)
|
365
410
|
|
366
411
|
return env
|
367
412
|
|
368
413
|
def _post_validate_changed_when(self, attr, value, templar):
|
369
|
-
|
414
|
+
"""
|
370
415
|
changed_when is evaluated after the execution of the task is complete,
|
371
416
|
and should not be templated during the regular post_validate step.
|
372
|
-
|
417
|
+
"""
|
373
418
|
return value
|
374
419
|
|
375
420
|
def _post_validate_failed_when(self, attr, value, templar):
|
376
|
-
|
421
|
+
"""
|
377
422
|
failed_when is evaluated after the execution of the task is complete,
|
378
423
|
and should not be templated during the regular post_validate step.
|
379
|
-
|
424
|
+
"""
|
380
425
|
return value
|
381
426
|
|
382
427
|
def _post_validate_until(self, attr, value, templar):
|
383
|
-
|
428
|
+
"""
|
384
429
|
until is evaluated after the execution of the task is complete,
|
385
430
|
and should not be templated during the regular post_validate step.
|
386
|
-
|
431
|
+
"""
|
387
432
|
return value
|
388
433
|
|
389
434
|
def get_vars(self):
|
@@ -408,7 +453,7 @@ class Task(Base, Conditional, Taggable, CollectionSearch, Notifiable, Delegatabl
|
|
408
453
|
all_vars |= self.vars
|
409
454
|
return all_vars
|
410
455
|
|
411
|
-
def copy(self, exclude_parent=False, exclude_tasks=False):
|
456
|
+
def copy(self, exclude_parent: bool = False, exclude_tasks: bool = False) -> Task:
|
412
457
|
new_me = super(Task, self).copy()
|
413
458
|
|
414
459
|
new_me._parent = None
|
@@ -473,11 +518,11 @@ class Task(Base, Conditional, Taggable, CollectionSearch, Notifiable, Delegatabl
|
|
473
518
|
super(Task, self).deserialize(data)
|
474
519
|
|
475
520
|
def set_loader(self, loader):
|
476
|
-
|
521
|
+
"""
|
477
522
|
Sets the loader on this object and recursively on parent, child objects.
|
478
523
|
This is used primarily after the Task has been serialized/deserialized, which
|
479
524
|
does not preserve the loader.
|
480
|
-
|
525
|
+
"""
|
481
526
|
|
482
527
|
self._loader = loader
|
483
528
|
|
@@ -485,9 +530,9 @@ class Task(Base, Conditional, Taggable, CollectionSearch, Notifiable, Delegatabl
|
|
485
530
|
self._parent.set_loader(loader)
|
486
531
|
|
487
532
|
def _get_parent_attribute(self, attr, omit=False):
|
488
|
-
|
533
|
+
"""
|
489
534
|
Generic logic to get the attribute or parent attribute for a task value.
|
490
|
-
|
535
|
+
"""
|
491
536
|
fattr = self.fattributes[attr]
|
492
537
|
|
493
538
|
extend = fattr.extend
|
@@ -542,3 +587,28 @@ class Task(Base, Conditional, Taggable, CollectionSearch, Notifiable, Delegatabl
|
|
542
587
|
while not isinstance(parent, Block):
|
543
588
|
parent = parent._parent
|
544
589
|
return parent._play
|
590
|
+
|
591
|
+
def dump_attrs(self):
|
592
|
+
"""Override to smuggle important non-FieldAttribute values back to the controller."""
|
593
|
+
attrs = super().dump_attrs()
|
594
|
+
attrs.update(resolved_action=self.resolved_action)
|
595
|
+
return attrs
|
596
|
+
|
597
|
+
def _resolve_conditional(
|
598
|
+
self,
|
599
|
+
conditional: list[str | bool],
|
600
|
+
variables: dict[str, t.Any],
|
601
|
+
*,
|
602
|
+
result_context: dict[str, t.Any] | None = None,
|
603
|
+
) -> bool:
|
604
|
+
"""Loops through the conditionals set on this object, returning False if any of them evaluate as such, as well as the condition that was False."""
|
605
|
+
engine = TemplateEngine(self._loader, variables=variables)
|
606
|
+
|
607
|
+
for item in conditional:
|
608
|
+
if not engine.evaluate_conditional(item):
|
609
|
+
if result_context is not None:
|
610
|
+
result_context.update(false_condition=item)
|
611
|
+
|
612
|
+
return False
|
613
|
+
|
614
|
+
return True
|
ansible/playbook/task_include.py
CHANGED
@@ -19,10 +19,10 @@ from __future__ import annotations
|
|
19
19
|
|
20
20
|
import ansible.constants as C
|
21
21
|
from ansible.errors import AnsibleParserError
|
22
|
+
from ansible.module_utils.common.sentinel import Sentinel
|
22
23
|
from ansible.playbook.block import Block
|
23
24
|
from ansible.playbook.task import Task
|
24
25
|
from ansible.utils.display import Display
|
25
|
-
from ansible.utils.sentinel import Sentinel
|
26
26
|
|
27
27
|
__all__ = ['TaskInclude']
|
28
28
|
|
@@ -58,12 +58,12 @@ class TaskInclude(Task):
|
|
58
58
|
return task
|
59
59
|
|
60
60
|
def check_options(self, task, data):
|
61
|
-
|
61
|
+
"""
|
62
62
|
Method for options validation to use in 'load_data' for TaskInclude and HandlerTaskInclude
|
63
63
|
since they share the same validations. It is not named 'validate_options' on purpose
|
64
64
|
to prevent confusion with '_validate_*" methods. Note that the task passed might be changed
|
65
65
|
as a side-effect of this method.
|
66
|
-
|
66
|
+
"""
|
67
67
|
my_arg_names = frozenset(task.args.keys())
|
68
68
|
|
69
69
|
# validate bad args, otherwise we silently ignore
|
@@ -104,10 +104,10 @@ class TaskInclude(Task):
|
|
104
104
|
return new_me
|
105
105
|
|
106
106
|
def build_parent_block(self):
|
107
|
-
|
107
|
+
"""
|
108
108
|
This method is used to create the parent block for the included tasks
|
109
109
|
when ``apply`` is specified
|
110
|
-
|
110
|
+
"""
|
111
111
|
apply_attrs = self.args.pop('apply', {})
|
112
112
|
if apply_attrs:
|
113
113
|
apply_attrs['block'] = []
|
ansible/plugins/__init__.py
CHANGED
@@ -19,17 +19,16 @@
|
|
19
19
|
|
20
20
|
from __future__ import annotations
|
21
21
|
|
22
|
-
|
23
|
-
|
22
|
+
import abc
|
24
23
|
import types
|
25
24
|
import typing as t
|
26
25
|
|
27
26
|
from ansible import constants as C
|
28
27
|
from ansible.errors import AnsibleError
|
29
|
-
from ansible.module_utils.common.text.converters import to_native
|
30
|
-
from ansible.module_utils.six import string_types
|
31
28
|
from ansible.utils.display import Display
|
32
29
|
|
30
|
+
from ansible.module_utils._internal import _plugin_exec_context
|
31
|
+
|
33
32
|
display = Display()
|
34
33
|
|
35
34
|
if t.TYPE_CHECKING:
|
@@ -42,13 +41,32 @@ PLUGIN_PATH_CACHE = {} # type: dict[str, dict[str, dict[str, PluginPathContext]
|
|
42
41
|
|
43
42
|
|
44
43
|
def get_plugin_class(obj):
|
45
|
-
if isinstance(obj,
|
44
|
+
if isinstance(obj, str):
|
46
45
|
return obj.lower().replace('module', '')
|
47
46
|
else:
|
48
47
|
return obj.__class__.__name__.lower().replace('module', '')
|
49
48
|
|
50
49
|
|
51
|
-
class
|
50
|
+
class _ConfigurablePlugin(t.Protocol):
|
51
|
+
"""Protocol to provide type-safe access to config for plugin-related mixins."""
|
52
|
+
|
53
|
+
def get_option(self, option: str, hostvars: dict[str, object] | None = None) -> object: ...
|
54
|
+
|
55
|
+
|
56
|
+
class _AnsiblePluginInfoMixin(_plugin_exec_context.HasPluginInfo):
|
57
|
+
"""Mixin to provide type annotations and default values for existing PluginLoader-set load-time attrs."""
|
58
|
+
_original_path: str | None = None
|
59
|
+
_load_name: str | None = None
|
60
|
+
_redirected_names: list[str] | None = None
|
61
|
+
ansible_aliases: list[str] | None = None
|
62
|
+
ansible_name: str | None = None
|
63
|
+
|
64
|
+
@property
|
65
|
+
def plugin_type(self) -> str:
|
66
|
+
return self.__class__.__name__.lower().replace('module', '')
|
67
|
+
|
68
|
+
|
69
|
+
class AnsiblePlugin(_AnsiblePluginInfoMixin, _ConfigurablePlugin, metaclass=abc.ABCMeta):
|
52
70
|
|
53
71
|
# Set by plugin loader
|
54
72
|
_load_name: str
|
@@ -81,7 +99,7 @@ class AnsiblePlugin(ABC):
|
|
81
99
|
try:
|
82
100
|
option_value, origin = C.config.get_config_value_and_origin(option, plugin_type=self.plugin_type, plugin_name=self._load_name, variables=hostvars)
|
83
101
|
except AnsibleError as e:
|
84
|
-
raise KeyError(
|
102
|
+
raise KeyError(str(e))
|
85
103
|
return option_value, origin
|
86
104
|
|
87
105
|
def get_option(self, option, hostvars=None):
|
@@ -102,13 +120,13 @@ class AnsiblePlugin(ABC):
|
|
102
120
|
C.handle_config_noise(display)
|
103
121
|
|
104
122
|
def set_options(self, task_keys=None, var_options=None, direct=None):
|
105
|
-
|
123
|
+
"""
|
106
124
|
Sets the _options attribute with the configuration/keyword information for this plugin
|
107
125
|
|
108
126
|
:arg task_keys: Dict with playbook keywords that affect this option
|
109
127
|
:arg var_options: Dict with either 'connection variables'
|
110
128
|
:arg direct: Dict with 'direct assignment'
|
111
|
-
|
129
|
+
"""
|
112
130
|
self._options = C.config.get_plugin_options(self.plugin_type, self._load_name, keys=task_keys, variables=var_options, direct=direct)
|
113
131
|
|
114
132
|
# allow extras/wildcards from vars that are not directly consumed in configuration
|
@@ -123,13 +141,9 @@ class AnsiblePlugin(ABC):
|
|
123
141
|
self.set_options()
|
124
142
|
return option in self._options
|
125
143
|
|
126
|
-
@property
|
127
|
-
def plugin_type(self):
|
128
|
-
return self.__class__.__name__.lower().replace('module', '')
|
129
|
-
|
130
144
|
@property
|
131
145
|
def option_definitions(self):
|
132
|
-
if self._defs is None:
|
146
|
+
if (not hasattr(self, "_defs")) or self._defs is None:
|
133
147
|
self._defs = C.config.get_configuration_definitions(plugin_type=self.plugin_type, name=self._load_name)
|
134
148
|
return self._defs
|
135
149
|
|
@@ -137,23 +151,56 @@ class AnsiblePlugin(ABC):
|
|
137
151
|
# FIXME: standardize required check based on config
|
138
152
|
pass
|
139
153
|
|
154
|
+
def __repr__(self):
|
155
|
+
ansible_name = getattr(self, 'ansible_name', '(unknown)')
|
156
|
+
load_name = getattr(self, '_load_name', '(unknown)')
|
157
|
+
return f'{type(self).__name__}(plugin_type={self.plugin_type!r}, {ansible_name=!r}, {load_name=!r})'
|
140
158
|
|
141
|
-
class AnsibleJinja2Plugin(AnsiblePlugin):
|
142
|
-
|
143
|
-
def __init__(self, function):
|
144
159
|
|
160
|
+
class AnsibleJinja2Plugin(AnsiblePlugin, metaclass=abc.ABCMeta):
|
161
|
+
def __init__(self, function: t.Callable) -> None:
|
145
162
|
super(AnsibleJinja2Plugin, self).__init__()
|
146
163
|
self._function = function
|
147
164
|
|
165
|
+
# Declare support for markers. Plugins with `False` here will never be invoked with markers for top-level arguments.
|
166
|
+
self.accept_args_markers = getattr(self._function, 'accept_args_markers', False)
|
167
|
+
self.accept_lazy_markers = getattr(self._function, 'accept_lazy_markers', False)
|
168
|
+
|
148
169
|
@property
|
149
|
-
|
150
|
-
|
170
|
+
@abc.abstractmethod
|
171
|
+
def plugin_type(self) -> str:
|
172
|
+
...
|
151
173
|
|
152
|
-
def _no_options(self, *args, **kwargs):
|
174
|
+
def _no_options(self, *args, **kwargs) -> t.NoReturn:
|
153
175
|
raise NotImplementedError()
|
154
176
|
|
155
177
|
has_option = get_option = get_options = option_definitions = set_option = set_options = _no_options
|
156
178
|
|
157
179
|
@property
|
158
|
-
def j2_function(self):
|
180
|
+
def j2_function(self) -> t.Callable:
|
159
181
|
return self._function
|
182
|
+
|
183
|
+
|
184
|
+
_TCallable = t.TypeVar('_TCallable', bound=t.Callable)
|
185
|
+
|
186
|
+
|
187
|
+
def accept_args_markers(plugin: _TCallable) -> _TCallable:
|
188
|
+
"""
|
189
|
+
A decorator to mark a Jinja plugin as capable of handling `Marker` values for its top-level arguments.
|
190
|
+
Non-decorated plugin invocation is skipped when a top-level argument is a `Marker`, with the first such value substituted as the plugin result.
|
191
|
+
This ensures that only plugins which understand `Marker` instances for top-level arguments will encounter them.
|
192
|
+
"""
|
193
|
+
plugin.accept_args_markers = True
|
194
|
+
|
195
|
+
return plugin
|
196
|
+
|
197
|
+
|
198
|
+
def accept_lazy_markers(plugin: _TCallable) -> _TCallable:
|
199
|
+
"""
|
200
|
+
A decorator to mark a Jinja plugin as capable of handling `Marker` values retrieved from lazy containers.
|
201
|
+
Non-decorated plugins will trigger a `MarkerError` exception when attempting to retrieve a `Marker` from a lazy container.
|
202
|
+
This ensures that only plugins which understand lazy retrieval of `Marker` instances will encounter them.
|
203
|
+
"""
|
204
|
+
plugin.accept_lazy_markers = True
|
205
|
+
|
206
|
+
return plugin
|