ansible-core 2.18.5rc1__py3-none-any.whl → 2.19.0b1__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/_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 +160 -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 +198 -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 +351 -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 +153 -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 +48 -46
- 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 +165 -108
- 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 +136 -76
- ansible/executor/stats.py +5 -5
- ansible/executor/task_executor.py +237 -236
- ansible/executor/task_queue_manager.py +62 -38
- ansible/executor/task_result.py +21 -12
- 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 +77 -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 +154 -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/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 +36 -339
- 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 +6 -15
- 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 +141 -123
- ansible/plugins/callback/default.py +30 -23
- ansible/plugins/callback/junit.py +28 -24
- ansible/plugins/callback/minimal.py +17 -14
- ansible/plugins/callback/oneline.py +13 -7
- ansible/plugins/callback/tree.py +10 -6
- 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 +218 -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 +94 -113
- ansible/plugins/strategy/debug.py +2 -2
- ansible/plugins/strategy/free.py +13 -28
- ansible/plugins/strategy/host_pinned.py +2 -2
- ansible/plugins/strategy/linear.py +31 -33
- ansible/plugins/terminal/__init__.py +4 -4
- ansible/plugins/test/__init__.py +7 -2
- ansible/plugins/test/core.py +54 -20
- 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 +368 -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 +428 -58
- 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 +28 -8
- ansible/utils/version.py +2 -2
- ansible/vars/clean.py +4 -4
- ansible/vars/hostvars.py +60 -90
- ansible/vars/manager.py +205 -264
- ansible/vars/reserved.py +8 -9
- ansible_core-2.19.0b1.dist-info/BSD-3-Clause.txt +28 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b1.dist-info}/METADATA +5 -4
- ansible_core-2.19.0b1.dist-info/RECORD +1070 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b1.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/utils/jsonify.py +0 -36
- 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.0b1.dist-info}/Apache-License.txt +0 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b1.dist-info}/COPYING +0 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b1.dist-info}/MIT-license.txt +0 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b1.dist-info}/PSF-license.txt +0 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b1.dist-info}/entry_points.txt +0 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b1.dist-info}/simplified_bsd.txt +0 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b1.dist-info}/top_level.txt +0 -0
ansible/plugins/shell/sh.py
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
4
4
|
from __future__ import annotations
|
5
5
|
|
6
|
-
DOCUMENTATION =
|
6
|
+
DOCUMENTATION = """
|
7
7
|
name: sh
|
8
8
|
short_description: "POSIX shell (/bin/sh)"
|
9
9
|
version_added: historical
|
@@ -11,7 +11,7 @@ description:
|
|
11
11
|
- This shell plugin is the one you want to use on most Unix systems, it is the most compatible and widely installed shell.
|
12
12
|
extends_documentation_fragment:
|
13
13
|
- shell_common
|
14
|
-
|
14
|
+
"""
|
15
15
|
|
16
16
|
from ansible.plugins.shell import ShellBase
|
17
17
|
|
@@ -29,6 +29,7 @@ class ShellModule(ShellBase):
|
|
29
29
|
|
30
30
|
# commonly used
|
31
31
|
ECHO = 'echo'
|
32
|
+
CD = 'cd'
|
32
33
|
COMMAND_SEP = ';'
|
33
34
|
|
34
35
|
# How to end lines in a python script one-liner
|
@@ -30,32 +30,26 @@ import typing as t
|
|
30
30
|
from collections import deque
|
31
31
|
|
32
32
|
|
33
|
-
from jinja2.exceptions import UndefinedError
|
34
|
-
|
35
33
|
from ansible import constants as C
|
36
34
|
from ansible import context
|
37
|
-
from ansible.errors import AnsibleError, AnsibleFileNotFound,
|
38
|
-
from ansible.executor import action_write_locks
|
35
|
+
from ansible.errors import AnsibleError, AnsibleFileNotFound, AnsibleParserError, AnsibleTemplateError
|
39
36
|
from ansible.executor.play_iterator import IteratingStates, PlayIterator
|
40
37
|
from ansible.executor.process.worker import WorkerProcess
|
41
38
|
from ansible.executor.task_result import TaskResult
|
42
|
-
from ansible.executor.task_queue_manager import CallbackSend, DisplaySend, PromptSend
|
39
|
+
from ansible.executor.task_queue_manager import CallbackSend, DisplaySend, PromptSend, TaskQueueManager
|
43
40
|
from ansible.module_utils.six import string_types
|
44
41
|
from ansible.module_utils.common.text.converters import to_text
|
45
42
|
from ansible.module_utils.connection import Connection, ConnectionError
|
46
|
-
from ansible.playbook.conditional import Conditional
|
47
43
|
from ansible.playbook.handler import Handler
|
48
44
|
from ansible.playbook.helpers import load_list_of_blocks
|
49
45
|
from ansible.playbook.task import Task
|
50
46
|
from ansible.playbook.task_include import TaskInclude
|
51
47
|
from ansible.plugins import loader as plugin_loader
|
52
|
-
from ansible.
|
48
|
+
from ansible._internal._templating._engine import TemplateEngine
|
53
49
|
from ansible.utils.display import Display
|
54
50
|
from ansible.utils.fqcn import add_internal_fqcns
|
55
|
-
from ansible.utils.unsafe_proxy import wrap_var
|
56
51
|
from ansible.utils.sentinel import Sentinel
|
57
52
|
from ansible.utils.vars import combine_vars
|
58
|
-
from ansible.utils.multiprocessing import context as multiprocessing_context
|
59
53
|
from ansible.vars.clean import strip_internal_keys, module_response_deepcopy
|
60
54
|
|
61
55
|
display = Display()
|
@@ -75,22 +69,8 @@ class StrategySentinel:
|
|
75
69
|
|
76
70
|
_sentinel = StrategySentinel()
|
77
71
|
|
78
|
-
|
79
|
-
|
80
|
-
cond = None
|
81
|
-
if task.changed_when:
|
82
|
-
with templar.set_temporary_context(available_variables=task_vars):
|
83
|
-
cond = Conditional(loader=templar._loader)
|
84
|
-
cond.when = task.changed_when
|
85
|
-
result['changed'] = cond.evaluate_conditional(templar, templar.available_variables)
|
86
|
-
|
87
|
-
if task.failed_when:
|
88
|
-
with templar.set_temporary_context(available_variables=task_vars):
|
89
|
-
if cond is None:
|
90
|
-
cond = Conditional(loader=templar._loader)
|
91
|
-
cond.when = task.failed_when
|
92
|
-
failed_when_result = cond.evaluate_conditional(templar, templar.available_variables)
|
93
|
-
result['failed_when_result'] = result['failed'] = failed_when_result
|
72
|
+
if t.TYPE_CHECKING:
|
73
|
+
from ansible.inventory.host import Host
|
94
74
|
|
95
75
|
|
96
76
|
def _get_item_vars(result, task):
|
@@ -223,17 +203,17 @@ def debug_closure(func):
|
|
223
203
|
|
224
204
|
class StrategyBase:
|
225
205
|
|
226
|
-
|
206
|
+
"""
|
227
207
|
This is the base class for strategy plugins, which contains some common
|
228
208
|
code useful to all strategies like running handlers, cleanup actions, etc.
|
229
|
-
|
209
|
+
"""
|
230
210
|
|
231
211
|
# by default, strategies should support throttling but we allow individual
|
232
212
|
# strategies to disable this and either forego supporting it or managing
|
233
213
|
# the throttling internally (as `free` does)
|
234
214
|
ALLOW_BASE_THROTTLING = True
|
235
215
|
|
236
|
-
def __init__(self, tqm):
|
216
|
+
def __init__(self, tqm: TaskQueueManager) -> None:
|
237
217
|
self._tqm = tqm
|
238
218
|
self._inventory = tqm.get_inventory()
|
239
219
|
self._workers = tqm._workers
|
@@ -246,7 +226,7 @@ class StrategyBase:
|
|
246
226
|
# the task cache is a dictionary of tuples of (host.name, task._uuid)
|
247
227
|
# used to find the original task object of in-flight tasks and to store
|
248
228
|
# the task args/vars and play context info used to queue the task.
|
249
|
-
self._queued_task_cache = {}
|
229
|
+
self._queued_task_cache: dict[tuple[str, str], dict[str, t.Any]] = {}
|
250
230
|
|
251
231
|
# Backwards compat: self._display isn't really needed, just import the global display and use that.
|
252
232
|
self._display = display
|
@@ -257,13 +237,11 @@ class StrategyBase:
|
|
257
237
|
|
258
238
|
# this dictionary is used to keep track of hosts that have
|
259
239
|
# outstanding tasks still in queue
|
260
|
-
self._blocked_hosts = dict()
|
240
|
+
self._blocked_hosts: dict[str, bool] = dict()
|
261
241
|
|
262
|
-
self._results = deque()
|
242
|
+
self._results: deque[TaskResult] = deque()
|
263
243
|
self._results_lock = threading.Condition(threading.Lock())
|
264
244
|
|
265
|
-
self._worker_queues = dict()
|
266
|
-
|
267
245
|
# create the result processing thread for reading results in the background
|
268
246
|
self._results_thread = threading.Thread(target=results_thread_main, args=(self,))
|
269
247
|
self._results_thread.daemon = True
|
@@ -271,13 +249,13 @@ class StrategyBase:
|
|
271
249
|
|
272
250
|
# holds the list of active (persistent) connections to be shutdown at
|
273
251
|
# play completion
|
274
|
-
self._active_connections = dict()
|
252
|
+
self._active_connections: dict[str, str] = dict()
|
275
253
|
|
276
254
|
# Caches for get_host calls, to avoid calling excessively
|
277
255
|
# These values should be set at the top of the ``run`` method of each
|
278
256
|
# strategy plugin. Use ``_set_hosts_cache`` to set these values
|
279
|
-
self._hosts_cache = []
|
280
|
-
self._hosts_cache_all = []
|
257
|
+
self._hosts_cache: list[str] = []
|
258
|
+
self._hosts_cache_all: list[str] = []
|
281
259
|
|
282
260
|
self.debugger_active = C.ENABLE_TASK_DEBUGGER
|
283
261
|
|
@@ -289,7 +267,7 @@ class StrategyBase:
|
|
289
267
|
if not refresh and all((self._hosts_cache, self._hosts_cache_all)):
|
290
268
|
return
|
291
269
|
|
292
|
-
if not play.finalized and
|
270
|
+
if not play.finalized and TemplateEngine().is_template(play.hosts):
|
293
271
|
_pattern = 'all'
|
294
272
|
else:
|
295
273
|
_pattern = play.hosts or 'all'
|
@@ -341,40 +319,25 @@ class StrategyBase:
|
|
341
319
|
return [host for host in self._hosts_cache if host in self._tqm._failed_hosts]
|
342
320
|
|
343
321
|
def add_tqm_variables(self, vars, play):
|
344
|
-
|
322
|
+
"""
|
345
323
|
Base class method to add extra variables/information to the list of task
|
346
324
|
vars sent through the executor engine regarding the task queue manager state.
|
347
|
-
|
325
|
+
"""
|
348
326
|
vars['ansible_current_hosts'] = self.get_hosts_remaining(play)
|
349
327
|
vars['ansible_failed_hosts'] = self.get_failed_hosts(play)
|
350
328
|
|
351
329
|
def _queue_task(self, host, task, task_vars, play_context):
|
352
|
-
|
330
|
+
""" handles queueing the task up to be sent to a worker """
|
353
331
|
|
354
332
|
display.debug("entering _queue_task() for %s/%s" % (host.name, task.action))
|
355
333
|
|
356
|
-
# Add a write lock for tasks.
|
357
|
-
# Maybe this should be added somewhere further up the call stack but
|
358
|
-
# this is the earliest in the code where we have task (1) extracted
|
359
|
-
# into its own variable and (2) there's only a single code path
|
360
|
-
# leading to the module being run. This is called by two
|
361
|
-
# functions: linear.py::run(), and
|
362
|
-
# free.py::run() so we'd have to add to both to do it there.
|
363
|
-
# The next common higher level is __init__.py::run() and that has
|
364
|
-
# tasks inside of play_iterator so we'd have to extract them to do it
|
365
|
-
# there.
|
366
|
-
|
367
|
-
if task.action not in action_write_locks.action_write_locks:
|
368
|
-
display.debug('Creating lock for %s' % task.action)
|
369
|
-
action_write_locks.action_write_locks[task.action] = multiprocessing_context.Lock()
|
370
|
-
|
371
334
|
# create a templar and template things we need later for the queuing process
|
372
|
-
templar =
|
335
|
+
templar = TemplateEngine(loader=self._loader, variables=task_vars)
|
373
336
|
|
374
337
|
try:
|
375
338
|
throttle = int(templar.template(task.throttle))
|
376
|
-
except Exception as
|
377
|
-
raise AnsibleError("Failed to convert the throttle value to an integer.", obj=task.
|
339
|
+
except Exception as ex:
|
340
|
+
raise AnsibleError("Failed to convert the throttle value to an integer.", obj=task.throttle) from ex
|
378
341
|
|
379
342
|
# and then queue the new task
|
380
343
|
try:
|
@@ -400,6 +363,8 @@ class StrategyBase:
|
|
400
363
|
|
401
364
|
worker_prc = self._workers[self._cur_worker]
|
402
365
|
if worker_prc is None or not worker_prc.is_alive():
|
366
|
+
if worker_prc:
|
367
|
+
worker_prc.close()
|
403
368
|
self._queued_task_cache[(host.name, task._uuid)] = {
|
404
369
|
'host': host,
|
405
370
|
'task': task,
|
@@ -409,7 +374,16 @@ class StrategyBase:
|
|
409
374
|
|
410
375
|
# Pass WorkerProcess its strategy worker number so it can send an identifier along with intra-task requests
|
411
376
|
worker_prc = WorkerProcess(
|
412
|
-
self._final_q,
|
377
|
+
final_q=self._final_q,
|
378
|
+
task_vars=task_vars,
|
379
|
+
host=host,
|
380
|
+
task=task,
|
381
|
+
play_context=play_context,
|
382
|
+
loader=self._loader,
|
383
|
+
variable_manager=self._variable_manager,
|
384
|
+
shared_loader_obj=plugin_loader.get_plugin_loader_namespace(),
|
385
|
+
worker_id=self._cur_worker,
|
386
|
+
cliargs=context.CLIARGS,
|
413
387
|
)
|
414
388
|
self._workers[self._cur_worker] = worker_prc
|
415
389
|
self._tqm.send_callback('v2_runner_on_start', host, task)
|
@@ -508,34 +482,38 @@ class StrategyBase:
|
|
508
482
|
return task_result
|
509
483
|
|
510
484
|
def search_handlers_by_notification(self, notification: str, iterator: PlayIterator) -> t.Generator[Handler, None, None]:
|
511
|
-
templar = Templar(None)
|
512
485
|
handlers = [h for b in reversed(iterator._play.handlers) for h in b.block]
|
513
486
|
# iterate in reversed order since last handler loaded with the same name wins
|
514
487
|
for handler in handlers:
|
515
488
|
if not handler.name:
|
516
489
|
continue
|
490
|
+
|
517
491
|
if not handler.cached_name:
|
518
|
-
|
519
|
-
|
492
|
+
def variables_factory() -> dict[str, t.Any]:
|
493
|
+
return self._variable_manager.get_vars(
|
520
494
|
play=iterator._play,
|
521
495
|
task=handler,
|
522
496
|
_hosts=self._hosts_cache,
|
523
497
|
_hosts_all=self._hosts_cache_all
|
524
498
|
)
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
499
|
+
|
500
|
+
templar = TemplateEngine(variables_factory=variables_factory)
|
501
|
+
|
502
|
+
try:
|
503
|
+
handler.name = templar.template(handler.name)
|
504
|
+
except AnsibleTemplateError as e:
|
505
|
+
# We skip this handler due to the fact that it may be using
|
506
|
+
# a variable in the name that was conditionally included via
|
507
|
+
# set_fact or some other method, and we don't want to error
|
508
|
+
# out unnecessarily
|
509
|
+
if not handler.listen:
|
510
|
+
display.warning(
|
511
|
+
"Handler '%s' is unusable because it has no listen topics and "
|
512
|
+
"the name could not be templated (host-specific variables are "
|
513
|
+
"not supported in handler names). The error: %s" % (handler.name, to_text(e))
|
514
|
+
)
|
515
|
+
continue
|
516
|
+
|
539
517
|
handler.cached_name = True
|
540
518
|
|
541
519
|
# first we check with the full result of get_name(), which may
|
@@ -559,11 +537,11 @@ class StrategyBase:
|
|
559
537
|
yield handler
|
560
538
|
|
561
539
|
@debug_closure
|
562
|
-
def _process_pending_results(self, iterator, one_pass=False, max_passes=None):
|
563
|
-
|
540
|
+
def _process_pending_results(self, iterator: PlayIterator, one_pass: bool = False, max_passes: int | None = None) -> list[TaskResult]:
|
541
|
+
"""
|
564
542
|
Reads results off the final queue and takes appropriate action
|
565
543
|
based on the result (executing callbacks, updating state, etc.).
|
566
|
-
|
544
|
+
"""
|
567
545
|
ret_results = []
|
568
546
|
cur_pass = 0
|
569
547
|
while True:
|
@@ -576,7 +554,7 @@ class StrategyBase:
|
|
576
554
|
self._results_lock.release()
|
577
555
|
|
578
556
|
original_host = task_result._host
|
579
|
-
original_task = task_result._task
|
557
|
+
original_task: Task = task_result._task
|
580
558
|
|
581
559
|
# all host status messages contain 2 entries: (msg, task_result)
|
582
560
|
role_ran = False
|
@@ -609,7 +587,7 @@ class StrategyBase:
|
|
609
587
|
self._variable_manager.set_nonpersistent_facts(
|
610
588
|
original_host.name,
|
611
589
|
dict(
|
612
|
-
ansible_failed_task=
|
590
|
+
ansible_failed_task=original_task.serialize(),
|
613
591
|
ansible_failed_result=task_result._result,
|
614
592
|
),
|
615
593
|
)
|
@@ -651,7 +629,7 @@ class StrategyBase:
|
|
651
629
|
# otherwise depending on the setting either error or warn
|
652
630
|
host_state = iterator.get_state_for_host(original_host.name)
|
653
631
|
for notification in result_item['_ansible_notify']:
|
654
|
-
handler = Sentinel
|
632
|
+
handler: type[Sentinel] | Handler = Sentinel
|
655
633
|
for handler in self.search_handlers_by_notification(notification, iterator):
|
656
634
|
if host_state.run_state == IteratingStates.HANDLERS:
|
657
635
|
# we're currently iterating handlers, so we need to expand this now
|
@@ -692,8 +670,15 @@ class StrategyBase:
|
|
692
670
|
all_task_vars = combine_vars(found_task_vars, item_vars)
|
693
671
|
else:
|
694
672
|
all_task_vars = found_task_vars
|
695
|
-
all_task_vars[original_task.register] =
|
696
|
-
|
673
|
+
all_task_vars[original_task.register] = result_item
|
674
|
+
|
675
|
+
if original_task.changed_when:
|
676
|
+
result_item['changed'] = original_task._resolve_conditional(original_task.changed_when, all_task_vars)
|
677
|
+
|
678
|
+
if original_task.failed_when:
|
679
|
+
result_item['failed_when_result'] = result_item['failed'] = (
|
680
|
+
original_task._resolve_conditional(original_task.failed_when, all_task_vars))
|
681
|
+
|
697
682
|
if original_task.loop or original_task.loop_with:
|
698
683
|
new_item_result = TaskResult(
|
699
684
|
task_result._host,
|
@@ -798,10 +783,10 @@ class StrategyBase:
|
|
798
783
|
return ret_results
|
799
784
|
|
800
785
|
def _wait_on_pending_results(self, iterator):
|
801
|
-
|
786
|
+
"""
|
802
787
|
Wait for the shared counter to drop to zero, using a short sleep
|
803
788
|
between checks to ensure we don't spin lock
|
804
|
-
|
789
|
+
"""
|
805
790
|
|
806
791
|
ret_results = []
|
807
792
|
|
@@ -821,9 +806,9 @@ class StrategyBase:
|
|
821
806
|
return ret_results
|
822
807
|
|
823
808
|
def _copy_included_file(self, included_file):
|
824
|
-
|
809
|
+
"""
|
825
810
|
A proven safe and performant way to create a copy of an included file
|
826
|
-
|
811
|
+
"""
|
827
812
|
ti_copy = included_file._task.copy(exclude_parent=True)
|
828
813
|
ti_copy._parent = included_file._task._parent
|
829
814
|
|
@@ -834,13 +819,13 @@ class StrategyBase:
|
|
834
819
|
return ti_copy
|
835
820
|
|
836
821
|
def _load_included_file(self, included_file, iterator, is_handler=False, handle_stats_and_callbacks=True):
|
837
|
-
|
822
|
+
"""
|
838
823
|
Loads an included YAML file of tasks, applying the optional set of variables.
|
839
824
|
|
840
825
|
Raises AnsibleError exception in case of a failure during including a file,
|
841
826
|
in such case the caller is responsible for marking the host(s) as failed
|
842
827
|
using PlayIterator.mark_host_failed().
|
843
|
-
|
828
|
+
"""
|
844
829
|
if handle_stats_and_callbacks:
|
845
830
|
display.deprecated(
|
846
831
|
"Reporting play recap stats and running callbacks functionality for "
|
@@ -852,7 +837,7 @@ class StrategyBase:
|
|
852
837
|
)
|
853
838
|
display.debug("loading included file: %s" % included_file._filename)
|
854
839
|
try:
|
855
|
-
data = self._loader.load_from_file(included_file._filename)
|
840
|
+
data = self._loader.load_from_file(included_file._filename, trusted_as_template=True)
|
856
841
|
if data is None:
|
857
842
|
return []
|
858
843
|
elif not isinstance(data, list):
|
@@ -920,19 +905,19 @@ class StrategyBase:
|
|
920
905
|
def _cond_not_supported_warn(self, task_name):
|
921
906
|
display.warning("%s task does not support when conditional" % task_name)
|
922
907
|
|
923
|
-
def _execute_meta(self, task, play_context, iterator, target_host):
|
908
|
+
def _execute_meta(self, task: Task, play_context, iterator, target_host):
|
909
|
+
task.resolved_action = 'ansible.builtin.meta' # _post_validate_args is never called for meta actions, so resolved_action hasn't been set
|
924
910
|
|
925
911
|
# meta tasks store their args in the _raw_params field of args,
|
926
912
|
# since they do not use k=v pairs, so get that
|
927
|
-
meta_action = task.
|
913
|
+
meta_action = task._get_meta()
|
928
914
|
|
929
|
-
def _evaluate_conditional(
|
915
|
+
def _evaluate_conditional(conditional_host: Host) -> bool:
|
930
916
|
if not task.when:
|
931
917
|
return True
|
932
|
-
|
933
|
-
|
934
|
-
|
935
|
-
return task.evaluate_conditional(templar, all_vars)
|
918
|
+
|
919
|
+
return task._resolve_conditional(task.when, self._variable_manager.get_vars(
|
920
|
+
play=iterator._play, host=conditional_host, task=task, _hosts=self._hosts_cache, _hosts_all=self._hosts_cache_all))
|
936
921
|
|
937
922
|
skipped = False
|
938
923
|
msg = meta_action
|
@@ -1032,7 +1017,7 @@ class StrategyBase:
|
|
1032
1017
|
if _evaluate_conditional(target_host):
|
1033
1018
|
while True:
|
1034
1019
|
state, task = iterator.get_next_task_for_host(target_host, peek=True)
|
1035
|
-
if task.
|
1020
|
+
if task._get_meta() == "role_complete":
|
1036
1021
|
break
|
1037
1022
|
iterator.set_state_for_host(target_host.name, state)
|
1038
1023
|
display.debug("'%s' skipped because role has been ended via 'end_role'" % task)
|
@@ -1043,7 +1028,7 @@ class StrategyBase:
|
|
1043
1028
|
elif meta_action == 'reset_connection':
|
1044
1029
|
all_vars = self._variable_manager.get_vars(play=iterator._play, host=target_host, task=task,
|
1045
1030
|
_hosts=self._hosts_cache, _hosts_all=self._hosts_cache_all)
|
1046
|
-
templar =
|
1031
|
+
templar = TemplateEngine(loader=self._loader, variables=all_vars)
|
1047
1032
|
|
1048
1033
|
# apply the given task's information to the connection info,
|
1049
1034
|
# which may override some fields already set by the play or
|
@@ -1085,15 +1070,17 @@ class StrategyBase:
|
|
1085
1070
|
else:
|
1086
1071
|
raise AnsibleError("invalid meta action requested: %s" % meta_action, obj=task._ds)
|
1087
1072
|
|
1088
|
-
result = {'msg': msg}
|
1073
|
+
result: dict[str, object] = {'msg': msg}
|
1089
1074
|
if skipped:
|
1090
1075
|
result['skipped'] = True
|
1091
1076
|
result['skip_reason'] = skip_reason
|
1092
1077
|
else:
|
1093
1078
|
result['changed'] = False
|
1094
1079
|
|
1095
|
-
if
|
1096
|
-
|
1080
|
+
header = skip_reason if skipped else msg
|
1081
|
+
if task.implicit:
|
1082
|
+
display.debug(f"META: {header}")
|
1083
|
+
else:
|
1097
1084
|
display.vv(f"META: {header}")
|
1098
1085
|
|
1099
1086
|
res = TaskResult(target_host, task, result)
|
@@ -1102,16 +1089,10 @@ class StrategyBase:
|
|
1102
1089
|
return [res]
|
1103
1090
|
|
1104
1091
|
def _get_cached_role(self, task, play):
|
1105
|
-
|
1106
|
-
role_cache = play.role_cache[role_path]
|
1107
|
-
try:
|
1108
|
-
idx = role_cache.index(task._role)
|
1109
|
-
return role_cache[idx]
|
1110
|
-
except ValueError:
|
1111
|
-
raise AnsibleError(f'Cannot locate {task._role.get_name()} in role cache')
|
1092
|
+
return play._get_cached_role(task._role)
|
1112
1093
|
|
1113
1094
|
def get_hosts_left(self, iterator):
|
1114
|
-
|
1095
|
+
""" returns list of available hosts for this iterator by filtering out unreachables """
|
1115
1096
|
|
1116
1097
|
hosts_left = []
|
1117
1098
|
for host in self._hosts_cache:
|
@@ -1123,7 +1104,7 @@ class StrategyBase:
|
|
1123
1104
|
return hosts_left
|
1124
1105
|
|
1125
1106
|
def update_active_connections(self, results):
|
1126
|
-
|
1107
|
+
""" updates the current active persistent connections """
|
1127
1108
|
for r in results:
|
1128
1109
|
if 'args' in r._task_fields:
|
1129
1110
|
socket_path = r._task_fields['args'].get('_ansible_socket')
|
@@ -1195,7 +1176,7 @@ class Debugger(cmd.Cmd):
|
|
1195
1176
|
|
1196
1177
|
def do_update_task(self, args):
|
1197
1178
|
"""Recreate the task from ``task._ds``, and template with updated ``task_vars``"""
|
1198
|
-
templar =
|
1179
|
+
templar = TemplateEngine(variables=self.scope['task_vars'])
|
1199
1180
|
task = self.scope['task']
|
1200
1181
|
task = task.load_data(task._ds)
|
1201
1182
|
task.post_validate(templar)
|
@@ -14,14 +14,14 @@
|
|
14
14
|
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
15
15
|
from __future__ import annotations
|
16
16
|
|
17
|
-
DOCUMENTATION =
|
17
|
+
DOCUMENTATION = """
|
18
18
|
name: debug
|
19
19
|
short_description: Executes tasks in interactive debug session.
|
20
20
|
description:
|
21
21
|
- Task execution is 'linear' but controlled by an interactive debug session.
|
22
22
|
version_added: "2.1"
|
23
23
|
author: Kishin Yagami (!UNKNOWN)
|
24
|
-
|
24
|
+
"""
|
25
25
|
|
26
26
|
from ansible.plugins.strategy.linear import StrategyModule as LinearStrategyModule
|
27
27
|
|
ansible/plugins/strategy/free.py
CHANGED
@@ -16,7 +16,7 @@
|
|
16
16
|
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
17
17
|
from __future__ import annotations
|
18
18
|
|
19
|
-
DOCUMENTATION =
|
19
|
+
DOCUMENTATION = """
|
20
20
|
name: free
|
21
21
|
short_description: Executes tasks without waiting for all hosts
|
22
22
|
description:
|
@@ -27,7 +27,7 @@ DOCUMENTATION = '''
|
|
27
27
|
won't hold up the rest of the hosts and tasks.
|
28
28
|
version_added: "2.0"
|
29
29
|
author: Ansible Core Team
|
30
|
-
|
30
|
+
"""
|
31
31
|
|
32
32
|
import time
|
33
33
|
|
@@ -37,8 +37,7 @@ from ansible.playbook.handler import Handler
|
|
37
37
|
from ansible.playbook.included_file import IncludedFile
|
38
38
|
from ansible.plugins.loader import action_loader
|
39
39
|
from ansible.plugins.strategy import StrategyBase
|
40
|
-
from ansible.
|
41
|
-
from ansible.module_utils.common.text.converters import to_text
|
40
|
+
from ansible._internal._templating._engine import TemplateEngine
|
42
41
|
from ansible.utils.display import Display
|
43
42
|
|
44
43
|
display = Display()
|
@@ -54,7 +53,7 @@ class StrategyModule(StrategyBase):
|
|
54
53
|
self._host_pinned = False
|
55
54
|
|
56
55
|
def run(self, iterator, play_context):
|
57
|
-
|
56
|
+
"""
|
58
57
|
The "free" strategy is a bit more complex, in that it allows tasks to
|
59
58
|
be sent to hosts as quickly as they can be processed. This means that
|
60
59
|
some hosts may finish very quickly if run tasks result in little or no
|
@@ -65,7 +64,7 @@ class StrategyModule(StrategyBase):
|
|
65
64
|
and starting the search from there as opposed to the top of the hosts
|
66
65
|
list again, which would end up favoring hosts near the beginning of the
|
67
66
|
list.
|
68
|
-
|
67
|
+
"""
|
69
68
|
|
70
69
|
# the last host to be given a task
|
71
70
|
last_host = 0
|
@@ -124,13 +123,13 @@ class StrategyModule(StrategyBase):
|
|
124
123
|
_hosts=self._hosts_cache,
|
125
124
|
_hosts_all=self._hosts_cache_all)
|
126
125
|
self.add_tqm_variables(task_vars, play=iterator._play)
|
127
|
-
templar =
|
126
|
+
templar = TemplateEngine(loader=self._loader, variables=task_vars)
|
128
127
|
display.debug("done getting variables", host=host_name)
|
129
128
|
|
130
129
|
try:
|
131
130
|
throttle = int(templar.template(task.throttle))
|
132
|
-
except Exception as
|
133
|
-
raise AnsibleError("Failed to convert the throttle value to an integer.", obj=task.
|
131
|
+
except Exception as ex:
|
132
|
+
raise AnsibleError("Failed to convert the throttle value to an integer.", obj=task.throttle) from ex
|
134
133
|
|
135
134
|
if throttle > 0:
|
136
135
|
same_tasks = 0
|
@@ -155,13 +154,7 @@ class StrategyModule(StrategyBase):
|
|
155
154
|
# corresponding action plugin
|
156
155
|
action = None
|
157
156
|
|
158
|
-
|
159
|
-
task.name = to_text(templar.template(task.name, fail_on_undefined=False), nonstring='empty')
|
160
|
-
display.debug("done templating", host=host_name)
|
161
|
-
except Exception:
|
162
|
-
# just ignore any errors during task name templating,
|
163
|
-
# we don't care if it just shows the raw name
|
164
|
-
display.debug("templating failed for some reason", host=host_name)
|
157
|
+
task.post_validate_attribute("name", templar=templar)
|
165
158
|
|
166
159
|
run_once = templar.template(task.run_once) or action and getattr(action, 'BYPASS_HOST_LOOP', False)
|
167
160
|
if run_once:
|
@@ -172,15 +165,6 @@ class StrategyModule(StrategyBase):
|
|
172
165
|
display.warning("Using run_once with the free strategy is not currently supported. This task will still be "
|
173
166
|
"executed for every host in the inventory list.")
|
174
167
|
|
175
|
-
# check to see if this task should be skipped, due to it being a member of a
|
176
|
-
# role which has already run (and whether that role allows duplicate execution)
|
177
|
-
if not isinstance(task, Handler) and task._role:
|
178
|
-
role_obj = self._get_cached_role(task, iterator._play)
|
179
|
-
if role_obj.has_run(host) and task._role._metadata.allow_duplicates is False:
|
180
|
-
display.debug("'%s' skipped because role has already run" % task, host=host_name)
|
181
|
-
del self._blocked_hosts[host_name]
|
182
|
-
continue
|
183
|
-
|
184
168
|
if task.action in C._ACTION_META:
|
185
169
|
if self._host_pinned:
|
186
170
|
meta_task_dummy_results_count += 1
|
@@ -264,11 +248,12 @@ class StrategyModule(StrategyBase):
|
|
264
248
|
iterator.handlers = [h for b in iterator._play.handlers for h in b.block]
|
265
249
|
except AnsibleParserError:
|
266
250
|
raise
|
267
|
-
except AnsibleError as
|
268
|
-
|
251
|
+
except AnsibleError as ex:
|
252
|
+
# FIXME: send the error to the callback; don't directly write to display here
|
253
|
+
display.error(ex)
|
269
254
|
for r in included_file._results:
|
270
255
|
r._result['failed'] = True
|
271
|
-
r._result['reason'] = str(
|
256
|
+
r._result['reason'] = str(ex)
|
272
257
|
self._tqm._stats.increment('failures', r._host.name)
|
273
258
|
self._tqm.send_callback('v2_runner_on_failed', r)
|
274
259
|
failed_includes_hosts.add(r._host)
|
@@ -16,7 +16,7 @@
|
|
16
16
|
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
17
17
|
from __future__ import annotations
|
18
18
|
|
19
|
-
DOCUMENTATION =
|
19
|
+
DOCUMENTATION = """
|
20
20
|
name: host_pinned
|
21
21
|
short_description: Executes tasks on each host without interruption
|
22
22
|
description:
|
@@ -28,7 +28,7 @@ DOCUMENTATION = '''
|
|
28
28
|
Other than that, it behaves just like the "free" strategy.
|
29
29
|
version_added: "2.7"
|
30
30
|
author: Ansible Core Team
|
31
|
-
|
31
|
+
"""
|
32
32
|
|
33
33
|
from ansible.plugins.strategy.free import StrategyModule as FreeStrategyModule
|
34
34
|
from ansible.utils.display import Display
|