ansible-core 2.18.7__py3-none-any.whl → 2.19.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ansible-core might be problematic. Click here for more details.
- ansible/_internal/__init__.py +53 -0
- ansible/_internal/_ansiballz/__init__.py +0 -0
- ansible/_internal/_ansiballz/_builder.py +101 -0
- ansible/_internal/_ansiballz/_wrapper.py +262 -0
- ansible/_internal/_collection_proxy.py +47 -0
- ansible/_internal/_datatag/__init__.py +0 -0
- ansible/_internal/_datatag/_tags.py +130 -0
- ansible/_internal/_datatag/_utils.py +19 -0
- ansible/_internal/_datatag/_wrappers.py +33 -0
- ansible/_internal/_errors/__init__.py +0 -0
- ansible/_internal/_errors/_alarm_timeout.py +66 -0
- ansible/_internal/_errors/_captured.py +123 -0
- ansible/_internal/_errors/_error_factory.py +89 -0
- ansible/_internal/_errors/_error_utils.py +240 -0
- ansible/_internal/_errors/_handler.py +91 -0
- ansible/_internal/_errors/_task_timeout.py +28 -0
- ansible/_internal/_event_formatting.py +127 -0
- ansible/_internal/_json/__init__.py +214 -0
- ansible/_internal/_json/_legacy_encoder.py +34 -0
- ansible/_internal/_json/_profiles/__init__.py +0 -0
- ansible/_internal/_json/_profiles/_cache_persistence.py +57 -0
- ansible/_internal/_json/_profiles/_inventory_legacy.py +40 -0
- ansible/_internal/_json/_profiles/_legacy.py +189 -0
- ansible/_internal/_locking.py +21 -0
- ansible/_internal/_plugins/__init__.py +0 -0
- ansible/_internal/_plugins/_cache.py +57 -0
- ansible/_internal/_ssh/__init__.py +0 -0
- ansible/_internal/_ssh/_agent_launch.py +91 -0
- ansible/_internal/_ssh/_ssh_agent.py +619 -0
- ansible/_internal/_task.py +78 -0
- ansible/_internal/_templating/__init__.py +12 -0
- ansible/_internal/_templating/_access.py +86 -0
- ansible/_internal/_templating/_chain_templar.py +63 -0
- ansible/_internal/_templating/_datatag.py +95 -0
- ansible/_internal/_templating/_engine.py +592 -0
- ansible/_internal/_templating/_errors.py +28 -0
- ansible/_internal/_templating/_jinja_bits.py +1106 -0
- ansible/_internal/_templating/_jinja_common.py +323 -0
- ansible/_internal/_templating/_jinja_patches.py +44 -0
- ansible/_internal/_templating/_jinja_plugins.py +375 -0
- ansible/_internal/_templating/_lazy_containers.py +633 -0
- ansible/_internal/_templating/_marker_behaviors.py +103 -0
- ansible/_internal/_templating/_template_vars.py +72 -0
- ansible/_internal/_templating/_transform.py +70 -0
- ansible/_internal/_templating/_utils.py +108 -0
- ansible/_internal/_testing.py +26 -0
- ansible/_internal/_wrapt.py +1052 -0
- ansible/_internal/_yaml/__init__.py +0 -0
- ansible/_internal/_yaml/_constructor.py +240 -0
- ansible/_internal/_yaml/_dumper.py +70 -0
- ansible/_internal/_yaml/_errors.py +166 -0
- ansible/_internal/_yaml/_loader.py +66 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/README.md +11 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/action/debug.py +36 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/apply_trust.py +19 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/dump_object.py +27 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/finalize.py +16 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/origin.py +18 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/python_literal_eval.py +24 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/python_literal_eval.yml +33 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/tag_names.py +16 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/true_type.py +17 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/unmask.py +49 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/lookup/config.py +21 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/lookup/config.yml +2 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged.py +15 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged.yml +19 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged_with.py +18 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged_with.yml +19 -0
- ansible/cli/__init__.py +93 -104
- ansible/cli/_ssh_askpass.py +54 -0
- ansible/cli/adhoc.py +20 -10
- ansible/cli/arguments/option_helpers.py +163 -10
- ansible/cli/config.py +43 -68
- ansible/cli/console.py +13 -11
- ansible/cli/doc.py +134 -77
- ansible/cli/galaxy.py +27 -20
- ansible/cli/inventory.py +28 -28
- ansible/cli/playbook.py +4 -12
- ansible/cli/pull.py +6 -3
- ansible/cli/scripts/ansible_connection_cli_stub.py +7 -7
- ansible/cli/vault.py +12 -11
- ansible/compat/__init__.py +2 -2
- ansible/compat/importlib_resources.py +9 -12
- ansible/config/base.yml +218 -133
- ansible/config/manager.py +220 -159
- ansible/constants.py +2 -65
- ansible/errors/__init__.py +350 -256
- ansible/executor/interpreter_discovery.py +28 -149
- ansible/executor/module_common.py +480 -514
- ansible/executor/play_iterator.py +22 -27
- ansible/executor/playbook_executor.py +11 -11
- ansible/executor/powershell/async_watchdog.ps1 +97 -102
- ansible/executor/powershell/async_wrapper.ps1 +204 -153
- ansible/executor/powershell/become_wrapper.ps1 +107 -144
- ansible/executor/powershell/bootstrap_wrapper.ps1 +46 -9
- ansible/executor/powershell/coverage_wrapper.ps1 +91 -135
- ansible/executor/powershell/exec_wrapper.ps1 +675 -196
- ansible/executor/powershell/module_manifest.py +469 -265
- ansible/executor/powershell/module_wrapper.ps1 +195 -186
- ansible/executor/powershell/powershell_expand_user.ps1 +20 -0
- ansible/executor/powershell/powershell_mkdtemp.ps1 +17 -0
- ansible/executor/powershell/psrp_fetch_file.ps1 +41 -0
- ansible/executor/powershell/psrp_put_file.ps1 +122 -0
- ansible/executor/powershell/winrm_fetch_file.ps1 +46 -0
- ansible/executor/powershell/winrm_put_file.ps1 +36 -0
- ansible/executor/process/worker.py +139 -149
- ansible/executor/stats.py +5 -5
- ansible/executor/task_executor.py +270 -297
- ansible/executor/task_queue_manager.py +135 -137
- ansible/executor/task_result.py +182 -79
- ansible/galaxy/__init__.py +2 -2
- ansible/galaxy/api.py +26 -25
- ansible/galaxy/collection/__init__.py +6 -14
- ansible/galaxy/collection/concrete_artifact_manager.py +12 -21
- ansible/galaxy/dependency_resolution/dataclasses.py +14 -4
- ansible/galaxy/dependency_resolution/providers.py +4 -4
- ansible/galaxy/dependency_resolution/reporters.py +81 -0
- ansible/galaxy/role.py +6 -10
- ansible/galaxy/token.py +28 -21
- ansible/inventory/data.py +47 -57
- ansible/inventory/group.py +50 -73
- ansible/inventory/helpers.py +9 -0
- ansible/inventory/host.py +37 -54
- ansible/inventory/manager.py +79 -34
- ansible/keyword_desc.yml +1 -1
- ansible/module_utils/_internal/__init__.py +55 -0
- ansible/module_utils/_internal/_ambient_context.py +58 -0
- ansible/module_utils/_internal/_ansiballz/__init__.py +0 -0
- ansible/module_utils/_internal/_ansiballz/_extensions/__init__.py +0 -0
- ansible/module_utils/_internal/_ansiballz/_extensions/_coverage.py +45 -0
- ansible/module_utils/_internal/_ansiballz/_extensions/_pydevd.py +62 -0
- ansible/module_utils/_internal/_ansiballz/_loader.py +81 -0
- ansible/module_utils/_internal/_ansiballz/_respawn.py +32 -0
- ansible/module_utils/_internal/_ansiballz/_respawn_wrapper.py +23 -0
- ansible/module_utils/_internal/_concurrent/_daemon_threading.py +1 -0
- ansible/module_utils/_internal/_dataclass_validation.py +217 -0
- ansible/module_utils/_internal/_datatag/__init__.py +961 -0
- ansible/module_utils/_internal/_datatag/_tags.py +16 -0
- ansible/module_utils/_internal/_debugging.py +31 -0
- ansible/module_utils/_internal/_deprecator.py +157 -0
- ansible/module_utils/_internal/_errors.py +101 -0
- ansible/module_utils/_internal/_event_utils.py +61 -0
- ansible/module_utils/_internal/_json/__init__.py +63 -0
- ansible/module_utils/_internal/_json/_legacy_encoder.py +26 -0
- ansible/module_utils/_internal/_json/_profiles/__init__.py +428 -0
- ansible/module_utils/_internal/_json/_profiles/_fallback_to_str.py +73 -0
- ansible/module_utils/_internal/_json/_profiles/_module_legacy_c2m.py +33 -0
- ansible/module_utils/_internal/_json/_profiles/_module_legacy_m2c.py +37 -0
- ansible/module_utils/_internal/_json/_profiles/_module_modern_c2m.py +35 -0
- ansible/module_utils/_internal/_json/_profiles/_module_modern_m2c.py +33 -0
- ansible/module_utils/_internal/_json/_profiles/_tagless.py +52 -0
- ansible/module_utils/_internal/_messages.py +130 -0
- ansible/module_utils/_internal/_patches/__init__.py +66 -0
- ansible/module_utils/_internal/_patches/_dataclass_annotation_patch.py +53 -0
- ansible/module_utils/_internal/_patches/_socket_patch.py +34 -0
- ansible/module_utils/_internal/_patches/_sys_intern_patch.py +34 -0
- ansible/module_utils/_internal/_plugin_info.py +38 -0
- ansible/module_utils/_internal/_stack.py +22 -0
- ansible/module_utils/_internal/_testing.py +0 -0
- ansible/module_utils/_internal/_text_utils.py +6 -0
- ansible/module_utils/_internal/_traceback.py +92 -0
- ansible/module_utils/_internal/_validation.py +14 -0
- ansible/module_utils/ansible_release.py +2 -2
- ansible/module_utils/api.py +1 -2
- ansible/module_utils/basic.py +303 -202
- ansible/module_utils/common/_utils.py +24 -28
- ansible/module_utils/common/arg_spec.py +8 -3
- ansible/module_utils/common/collections.py +7 -2
- ansible/module_utils/common/dict_transformations.py +2 -2
- ansible/module_utils/common/file.py +2 -2
- ansible/module_utils/common/json.py +90 -84
- ansible/module_utils/common/locale.py +2 -2
- ansible/module_utils/common/parameters.py +27 -24
- ansible/module_utils/common/process.py +2 -3
- ansible/module_utils/common/respawn.py +11 -33
- ansible/module_utils/common/sentinel.py +66 -0
- ansible/module_utils/common/sys_info.py +8 -8
- ansible/module_utils/common/text/converters.py +16 -37
- ansible/module_utils/common/validation.py +35 -24
- ansible/module_utils/common/warnings.py +143 -25
- ansible/module_utils/common/yaml.py +29 -3
- ansible/module_utils/compat/datetime.py +33 -21
- ansible/module_utils/compat/paramiko.py +21 -10
- ansible/module_utils/compat/typing.py +6 -5
- ansible/module_utils/connection.py +10 -13
- ansible/module_utils/csharp/Ansible.Basic.cs +15 -12
- ansible/module_utils/csharp/Ansible.Become.cs +1 -0
- ansible/module_utils/csharp/Ansible.Privilege.cs +2 -2
- ansible/module_utils/csharp/Ansible._Async.cs +517 -0
- ansible/module_utils/datatag.py +49 -0
- ansible/module_utils/distro/__init__.py +2 -2
- ansible/module_utils/facts/ansible_collector.py +4 -5
- ansible/module_utils/facts/collector.py +13 -14
- ansible/module_utils/facts/compat.py +4 -4
- ansible/module_utils/facts/default_collectors.py +1 -1
- ansible/module_utils/facts/hardware/aix.py +34 -0
- ansible/module_utils/facts/hardware/base.py +2 -2
- ansible/module_utils/facts/hardware/darwin.py +1 -3
- ansible/module_utils/facts/hardware/freebsd.py +2 -2
- ansible/module_utils/facts/hardware/linux.py +5 -5
- ansible/module_utils/facts/namespace.py +1 -1
- ansible/module_utils/facts/network/base.py +1 -1
- ansible/module_utils/facts/network/fc_wwn.py +1 -2
- ansible/module_utils/facts/network/iscsi.py +1 -2
- ansible/module_utils/facts/network/nvme.py +1 -2
- ansible/module_utils/facts/other/facter.py +2 -3
- ansible/module_utils/facts/other/ohai.py +2 -3
- ansible/module_utils/facts/sysctl.py +4 -6
- ansible/module_utils/facts/system/apparmor.py +1 -2
- ansible/module_utils/facts/system/caps.py +3 -3
- ansible/module_utils/facts/system/chroot.py +1 -2
- ansible/module_utils/facts/system/cmdline.py +1 -2
- ansible/module_utils/facts/system/date_time.py +5 -3
- ansible/module_utils/facts/system/distribution.py +27 -13
- ansible/module_utils/facts/system/dns.py +1 -1
- ansible/module_utils/facts/system/env.py +1 -2
- ansible/module_utils/facts/system/fips.py +7 -20
- ansible/module_utils/facts/system/loadavg.py +1 -2
- ansible/module_utils/facts/system/local.py +2 -3
- ansible/module_utils/facts/system/lsb.py +1 -2
- ansible/module_utils/facts/system/pkg_mgr.py +1 -2
- ansible/module_utils/facts/system/platform.py +1 -2
- ansible/module_utils/facts/system/python.py +1 -2
- ansible/module_utils/facts/system/selinux.py +1 -1
- ansible/module_utils/facts/system/service_mgr.py +1 -2
- ansible/module_utils/facts/system/ssh_pub_keys.py +1 -1
- ansible/module_utils/facts/system/systemd.py +1 -1
- ansible/module_utils/facts/system/user.py +1 -2
- ansible/module_utils/facts/utils.py +3 -3
- ansible/module_utils/facts/virtual/base.py +1 -1
- ansible/module_utils/facts/virtual/linux.py +3 -3
- ansible/module_utils/facts/virtual/sunos.py +3 -15
- ansible/module_utils/facts/virtual/sysctl.py +3 -16
- ansible/module_utils/json_utils.py +2 -2
- ansible/module_utils/parsing/convert_bool.py +7 -1
- ansible/module_utils/powershell/Ansible.ModuleUtils.AddType.psm1 +1 -1
- ansible/module_utils/powershell/Ansible.ModuleUtils.CamelConversion.psm1 +1 -1
- ansible/module_utils/powershell/Ansible.ModuleUtils.CommandUtil.psm1 +1 -1
- ansible/module_utils/powershell/Ansible.ModuleUtils.WebRequest.psm1 +1 -1
- ansible/module_utils/service.py +21 -31
- ansible/module_utils/splitter.py +7 -7
- ansible/module_utils/testing.py +31 -0
- ansible/module_utils/urls.py +64 -35
- ansible/modules/add_host.py +4 -4
- ansible/modules/apt.py +69 -49
- ansible/modules/apt_key.py +19 -12
- ansible/modules/apt_repository.py +32 -51
- ansible/modules/assemble.py +16 -14
- ansible/modules/assert.py +4 -4
- ansible/modules/async_status.py +24 -24
- ansible/modules/async_wrapper.py +20 -25
- ansible/modules/blockinfile.py +6 -7
- ansible/modules/command.py +13 -20
- ansible/modules/copy.py +60 -147
- ansible/modules/cron.py +24 -21
- ansible/modules/deb822_repository.py +8 -9
- ansible/modules/debconf.py +5 -5
- ansible/modules/debug.py +4 -4
- ansible/modules/dnf.py +8 -8
- ansible/modules/dnf5.py +39 -13
- ansible/modules/dpkg_selections.py +4 -4
- ansible/modules/expect.py +13 -15
- ansible/modules/fail.py +4 -4
- ansible/modules/fetch.py +4 -4
- ansible/modules/file.py +184 -144
- ansible/modules/find.py +22 -20
- ansible/modules/gather_facts.py +3 -3
- ansible/modules/get_url.py +77 -54
- ansible/modules/getent.py +7 -9
- ansible/modules/git.py +38 -38
- ansible/modules/group.py +6 -6
- ansible/modules/group_by.py +4 -4
- ansible/modules/hostname.py +15 -32
- ansible/modules/import_playbook.py +6 -6
- ansible/modules/import_role.py +6 -6
- ansible/modules/import_tasks.py +6 -6
- ansible/modules/include_role.py +6 -6
- ansible/modules/include_tasks.py +6 -6
- ansible/modules/include_vars.py +6 -6
- ansible/modules/iptables.py +86 -73
- ansible/modules/known_hosts.py +22 -24
- ansible/modules/lineinfile.py +5 -5
- ansible/modules/meta.py +4 -4
- ansible/modules/mount_facts.py +2 -2
- ansible/modules/package.py +10 -4
- ansible/modules/package_facts.py +22 -10
- ansible/modules/pause.py +6 -6
- ansible/modules/ping.py +6 -6
- ansible/modules/pip.py +21 -26
- ansible/modules/raw.py +6 -6
- ansible/modules/reboot.py +6 -6
- ansible/modules/replace.py +10 -14
- ansible/modules/rpm_key.py +7 -8
- ansible/modules/script.py +4 -4
- ansible/modules/service.py +10 -17
- ansible/modules/service_facts.py +87 -10
- ansible/modules/set_fact.py +5 -5
- ansible/modules/set_stats.py +4 -4
- ansible/modules/setup.py +2 -2
- ansible/modules/shell.py +6 -6
- ansible/modules/slurp.py +16 -19
- ansible/modules/stat.py +15 -31
- ansible/modules/subversion.py +15 -15
- ansible/modules/systemd.py +7 -7
- ansible/modules/systemd_service.py +7 -7
- ansible/modules/sysvinit.py +9 -9
- ansible/modules/tempfile.py +5 -6
- ansible/modules/template.py +6 -6
- ansible/modules/unarchive.py +38 -17
- ansible/modules/uri.py +33 -26
- ansible/modules/user.py +45 -32
- ansible/modules/validate_argument_spec.py +10 -7
- ansible/modules/wait_for.py +70 -60
- ansible/modules/wait_for_connection.py +6 -6
- ansible/modules/yum_repository.py +10 -9
- ansible/parsing/ajson.py +17 -37
- ansible/parsing/dataloader.py +99 -54
- ansible/parsing/mod_args.py +62 -60
- ansible/parsing/plugin_docs.py +21 -86
- ansible/parsing/quoting.py +1 -1
- ansible/parsing/splitter.py +27 -12
- ansible/parsing/utils/addresses.py +24 -24
- ansible/parsing/utils/jsonify.py +5 -1
- ansible/parsing/utils/yaml.py +32 -61
- ansible/parsing/vault/__init__.py +327 -99
- ansible/parsing/yaml/__init__.py +0 -18
- ansible/parsing/yaml/dumper.py +6 -120
- ansible/parsing/yaml/loader.py +6 -39
- ansible/parsing/yaml/objects.py +43 -335
- ansible/playbook/__init__.py +1 -1
- ansible/playbook/attribute.py +8 -3
- ansible/playbook/base.py +187 -134
- ansible/playbook/block.py +26 -24
- ansible/playbook/collectionsearch.py +1 -15
- ansible/playbook/conditional.py +3 -77
- ansible/playbook/handler.py +8 -2
- ansible/playbook/helpers.py +41 -53
- ansible/playbook/included_file.py +32 -26
- ansible/playbook/loop_control.py +2 -2
- ansible/playbook/play.py +85 -44
- ansible/playbook/play_context.py +14 -17
- ansible/playbook/playbook_include.py +27 -62
- ansible/playbook/role/__init__.py +64 -49
- ansible/playbook/role/definition.py +15 -17
- ansible/playbook/role/include.py +2 -4
- ansible/playbook/role/metadata.py +10 -11
- ansible/playbook/role_include.py +3 -3
- ansible/playbook/taggable.py +28 -12
- ansible/playbook/task.py +192 -121
- ansible/playbook/task_include.py +5 -5
- ansible/plugins/__init__.py +58 -26
- ansible/plugins/action/__init__.py +188 -186
- ansible/plugins/action/add_host.py +2 -2
- ansible/plugins/action/assemble.py +11 -18
- ansible/plugins/action/assert.py +55 -67
- ansible/plugins/action/async_status.py +7 -2
- ansible/plugins/action/copy.py +14 -17
- ansible/plugins/action/debug.py +37 -31
- ansible/plugins/action/dnf.py +3 -4
- ansible/plugins/action/fail.py +1 -1
- ansible/plugins/action/fetch.py +7 -8
- ansible/plugins/action/gather_facts.py +13 -14
- ansible/plugins/action/group_by.py +1 -1
- ansible/plugins/action/include_vars.py +10 -11
- ansible/plugins/action/package.py +8 -14
- ansible/plugins/action/pause.py +2 -2
- ansible/plugins/action/script.py +27 -38
- ansible/plugins/action/service.py +9 -18
- ansible/plugins/action/set_fact.py +3 -12
- ansible/plugins/action/set_stats.py +3 -8
- ansible/plugins/action/template.py +47 -67
- ansible/plugins/action/unarchive.py +6 -16
- ansible/plugins/action/uri.py +9 -20
- ansible/plugins/action/validate_argument_spec.py +5 -5
- ansible/plugins/action/wait_for_connection.py +1 -1
- ansible/plugins/become/__init__.py +31 -8
- ansible/plugins/become/runas.py +71 -0
- ansible/plugins/become/su.py +13 -8
- ansible/plugins/become/sudo.py +19 -0
- ansible/plugins/cache/__init__.py +52 -63
- ansible/plugins/cache/base.py +8 -0
- ansible/plugins/cache/jsonfile.py +10 -16
- ansible/plugins/cache/memory.py +6 -12
- ansible/plugins/callback/__init__.py +294 -201
- ansible/plugins/callback/default.py +99 -95
- ansible/plugins/callback/junit.py +44 -43
- ansible/plugins/callback/minimal.py +28 -25
- ansible/plugins/callback/oneline.py +34 -21
- ansible/plugins/callback/tree.py +27 -16
- ansible/plugins/connection/__init__.py +47 -34
- ansible/plugins/connection/local.py +156 -60
- ansible/plugins/connection/paramiko_ssh.py +34 -24
- ansible/plugins/connection/psrp.py +76 -165
- ansible/plugins/connection/ssh.py +326 -86
- ansible/plugins/connection/winrm.py +62 -141
- ansible/plugins/doc_fragments/action_common_attributes.py +14 -14
- ansible/plugins/doc_fragments/action_core.py +6 -6
- ansible/plugins/doc_fragments/backup.py +2 -2
- ansible/plugins/doc_fragments/checksum_common.py +27 -0
- ansible/plugins/doc_fragments/constructed.py +8 -4
- ansible/plugins/doc_fragments/decrypt.py +2 -2
- ansible/plugins/doc_fragments/default_callback.py +2 -2
- ansible/plugins/doc_fragments/files.py +2 -2
- ansible/plugins/doc_fragments/inventory_cache.py +2 -2
- ansible/plugins/doc_fragments/result_format_callback.py +2 -2
- ansible/plugins/doc_fragments/return_common.py +2 -2
- ansible/plugins/doc_fragments/template_common.py +4 -4
- ansible/plugins/doc_fragments/url.py +17 -1
- ansible/plugins/doc_fragments/url_windows.py +2 -2
- ansible/plugins/doc_fragments/validate.py +2 -2
- ansible/plugins/doc_fragments/vars_plugin_staging.py +2 -2
- ansible/plugins/filter/__init__.py +6 -2
- ansible/plugins/filter/b64decode.yml +22 -0
- ansible/plugins/filter/b64encode.yml +22 -0
- ansible/plugins/filter/bool.yml +11 -4
- ansible/plugins/filter/core.py +245 -120
- ansible/plugins/filter/encryption.py +42 -34
- ansible/plugins/filter/flatten.yml +3 -2
- ansible/plugins/filter/human_to_bytes.yml +1 -1
- ansible/plugins/filter/mathstuff.py +30 -37
- ansible/plugins/filter/password_hash.yml +8 -0
- ansible/plugins/filter/pow.yml +1 -1
- ansible/plugins/filter/regex_search.yml +1 -4
- ansible/plugins/filter/root.yml +1 -1
- ansible/plugins/filter/split.yml +1 -1
- ansible/plugins/filter/strftime.yml +3 -3
- ansible/plugins/filter/to_nice_yaml.yml +0 -4
- ansible/plugins/filter/to_uuid.yml +1 -1
- ansible/plugins/filter/to_yaml.yml +0 -4
- ansible/plugins/filter/unvault.yml +1 -1
- ansible/plugins/filter/urls.py +1 -1
- ansible/plugins/filter/urlsplit.py +8 -9
- ansible/plugins/filter/vault.yml +14 -9
- ansible/plugins/filter/win_basename.yml +6 -1
- ansible/plugins/filter/win_dirname.yml +5 -0
- ansible/plugins/inventory/__init__.py +107 -86
- ansible/plugins/inventory/advanced_host_list.py +7 -5
- ansible/plugins/inventory/auto.py +11 -4
- ansible/plugins/inventory/constructed.py +21 -24
- ansible/plugins/inventory/generator.py +16 -11
- ansible/plugins/inventory/host_list.py +7 -5
- ansible/plugins/inventory/ini.py +78 -44
- ansible/plugins/inventory/script.py +190 -120
- ansible/plugins/inventory/toml.py +16 -126
- ansible/plugins/inventory/yaml.py +10 -8
- ansible/plugins/list.py +72 -19
- ansible/plugins/loader.py +383 -198
- ansible/plugins/lookup/__init__.py +21 -4
- ansible/plugins/lookup/config.py +21 -35
- ansible/plugins/lookup/csvfile.py +19 -73
- ansible/plugins/lookup/dict.py +1 -6
- ansible/plugins/lookup/env.py +12 -9
- ansible/plugins/lookup/file.py +5 -8
- ansible/plugins/lookup/first_found.py +87 -55
- ansible/plugins/lookup/indexed_items.py +1 -10
- ansible/plugins/lookup/ini.py +14 -13
- ansible/plugins/lookup/items.py +1 -1
- ansible/plugins/lookup/lines.py +8 -1
- ansible/plugins/lookup/list.py +1 -1
- ansible/plugins/lookup/nested.py +2 -18
- ansible/plugins/lookup/password.py +5 -5
- ansible/plugins/lookup/pipe.py +5 -7
- ansible/plugins/lookup/sequence.py +18 -8
- ansible/plugins/lookup/subelements.py +1 -4
- ansible/plugins/lookup/template.py +47 -36
- ansible/plugins/lookup/together.py +0 -12
- ansible/plugins/lookup/unvault.py +1 -5
- ansible/plugins/lookup/url.py +4 -10
- ansible/plugins/lookup/vars.py +16 -24
- ansible/plugins/shell/__init__.py +58 -4
- ansible/plugins/shell/cmd.py +2 -2
- ansible/plugins/shell/powershell.py +106 -31
- ansible/plugins/shell/sh.py +13 -7
- ansible/plugins/strategy/__init__.py +168 -193
- ansible/plugins/strategy/debug.py +2 -2
- ansible/plugins/strategy/free.py +16 -31
- ansible/plugins/strategy/host_pinned.py +2 -2
- ansible/plugins/strategy/linear.py +41 -41
- ansible/plugins/terminal/__init__.py +4 -4
- ansible/plugins/test/__init__.py +7 -2
- ansible/plugins/test/core.py +75 -35
- ansible/plugins/test/files.py +1 -1
- ansible/plugins/test/finished.yml +1 -1
- ansible/plugins/test/mathstuff.py +3 -3
- ansible/plugins/test/uri.py +5 -8
- ansible/plugins/vars/host_group_vars.py +7 -14
- ansible/release.py +2 -2
- ansible/template/__init__.py +353 -943
- ansible/utils/__init__.py +0 -18
- ansible/utils/collection_loader/__init__.py +54 -5
- ansible/utils/collection_loader/_collection_config.py +5 -6
- ansible/utils/collection_loader/_collection_finder.py +82 -96
- ansible/utils/collection_loader/_collection_meta.py +15 -8
- ansible/utils/display.py +485 -73
- ansible/utils/encrypt.py +27 -19
- ansible/utils/fqcn.py +2 -2
- ansible/utils/galaxy.py +2 -2
- ansible/utils/hashing.py +8 -10
- ansible/utils/helpers.py +2 -2
- ansible/utils/listify.py +10 -8
- ansible/utils/lock.py +2 -2
- ansible/utils/path.py +10 -12
- ansible/utils/plugin_docs.py +16 -14
- ansible/utils/py3compat.py +2 -7
- ansible/utils/sentinel.py +4 -62
- ansible/utils/singleton.py +2 -0
- ansible/utils/ssh_functions.py +6 -2
- ansible/utils/unsafe_proxy.py +23 -332
- ansible/utils/vars.py +55 -8
- ansible/utils/version.py +2 -2
- ansible/vars/clean.py +5 -5
- ansible/vars/hostvars.py +60 -90
- ansible/vars/manager.py +220 -285
- ansible/vars/plugins.py +4 -4
- ansible/vars/reserved.py +13 -12
- {ansible_core-2.18.7.dist-info → ansible_core-2.19.0.dist-info}/METADATA +4 -3
- ansible_core-2.19.0.dist-info/RECORD +1097 -0
- ansible_core-2.19.0.dist-info/licenses/licenses/BSD-3-Clause.txt +28 -0
- ansible_test/_data/completion/docker.txt +7 -7
- ansible_test/_data/completion/remote.txt +6 -6
- ansible_test/_data/completion/windows.txt +1 -0
- ansible_test/_data/requirements/ansible.txt +2 -2
- ansible_test/_data/requirements/sanity.ansible-doc.txt +3 -3
- ansible_test/_data/requirements/sanity.changelog.txt +2 -2
- ansible_test/_data/requirements/sanity.import.plugin.txt +2 -2
- ansible_test/_data/requirements/sanity.pep8.txt +1 -1
- ansible_test/_data/requirements/sanity.pylint.txt +5 -5
- ansible_test/_data/requirements/sanity.validate-modules.txt +2 -2
- ansible_test/_data/requirements/sanity.yamllint.txt +1 -1
- ansible_test/_data/requirements/units.txt +1 -0
- ansible_test/_internal/__init__.py +6 -0
- ansible_test/_internal/ansible_util.py +3 -1
- ansible_test/_internal/become.py +1 -0
- ansible_test/_internal/bootstrap.py +1 -0
- ansible_test/_internal/cache.py +1 -0
- ansible_test/_internal/cgroup.py +1 -0
- ansible_test/_internal/ci/__init__.py +1 -0
- ansible_test/_internal/ci/azp.py +1 -0
- ansible_test/_internal/ci/local.py +1 -0
- ansible_test/_internal/classification/__init__.py +1 -0
- ansible_test/_internal/classification/common.py +1 -0
- ansible_test/_internal/classification/csharp.py +1 -0
- ansible_test/_internal/classification/powershell.py +1 -0
- ansible_test/_internal/classification/python.py +1 -0
- ansible_test/_internal/cli/__init__.py +1 -0
- ansible_test/_internal/cli/actions.py +1 -0
- ansible_test/_internal/cli/argparsing/__init__.py +1 -0
- ansible_test/_internal/cli/argparsing/actions.py +1 -0
- ansible_test/_internal/cli/argparsing/argcompletion.py +1 -0
- ansible_test/_internal/cli/argparsing/parsers.py +1 -0
- ansible_test/_internal/cli/commands/__init__.py +11 -5
- ansible_test/_internal/cli/commands/coverage/__init__.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/__init__.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/__init__.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/combine.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/expand.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/filter.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/generate.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/missing.py +1 -0
- ansible_test/_internal/cli/commands/coverage/combine.py +1 -0
- ansible_test/_internal/cli/commands/coverage/erase.py +1 -0
- ansible_test/_internal/cli/commands/coverage/html.py +1 -0
- ansible_test/_internal/cli/commands/coverage/report.py +1 -0
- ansible_test/_internal/cli/commands/coverage/xml.py +1 -0
- ansible_test/_internal/cli/commands/env.py +1 -0
- ansible_test/_internal/cli/commands/integration/__init__.py +1 -0
- ansible_test/_internal/cli/commands/integration/network.py +1 -0
- ansible_test/_internal/cli/commands/integration/posix.py +1 -0
- ansible_test/_internal/cli/commands/integration/windows.py +1 -0
- ansible_test/_internal/cli/commands/sanity.py +9 -0
- ansible_test/_internal/cli/commands/shell.py +1 -0
- ansible_test/_internal/cli/commands/units.py +1 -0
- ansible_test/_internal/cli/compat.py +1 -0
- ansible_test/_internal/cli/completers.py +1 -0
- ansible_test/_internal/cli/converters.py +1 -0
- ansible_test/_internal/cli/environments.py +52 -5
- ansible_test/_internal/cli/epilog.py +1 -0
- ansible_test/_internal/cli/parsers/__init__.py +1 -0
- ansible_test/_internal/cli/parsers/base_argument_parsers.py +1 -0
- ansible_test/_internal/cli/parsers/helpers.py +1 -0
- ansible_test/_internal/cli/parsers/host_config_parsers.py +1 -0
- ansible_test/_internal/cli/parsers/key_value_parsers.py +1 -0
- ansible_test/_internal/cli/parsers/value_parsers.py +1 -0
- ansible_test/_internal/commands/__init__.py +1 -0
- ansible_test/_internal/commands/coverage/__init__.py +3 -2
- ansible_test/_internal/commands/coverage/analyze/__init__.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/__init__.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/combine.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/expand.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/filter.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/generate.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/missing.py +1 -0
- ansible_test/_internal/commands/coverage/combine.py +2 -1
- ansible_test/_internal/commands/coverage/erase.py +1 -0
- ansible_test/_internal/commands/coverage/html.py +1 -0
- ansible_test/_internal/commands/coverage/report.py +1 -0
- ansible_test/_internal/commands/coverage/xml.py +1 -0
- ansible_test/_internal/commands/env/__init__.py +2 -0
- ansible_test/_internal/commands/integration/__init__.py +22 -5
- ansible_test/_internal/commands/integration/cloud/__init__.py +1 -0
- ansible_test/_internal/commands/integration/cloud/acme.py +2 -1
- ansible_test/_internal/commands/integration/cloud/aws.py +1 -0
- ansible_test/_internal/commands/integration/cloud/azure.py +1 -0
- ansible_test/_internal/commands/integration/cloud/cs.py +1 -0
- ansible_test/_internal/commands/integration/cloud/digitalocean.py +1 -0
- ansible_test/_internal/commands/integration/cloud/galaxy.py +3 -2
- ansible_test/_internal/commands/integration/cloud/hcloud.py +1 -0
- ansible_test/_internal/commands/integration/cloud/httptester.py +3 -2
- ansible_test/_internal/commands/integration/cloud/nios.py +2 -1
- ansible_test/_internal/commands/integration/cloud/opennebula.py +1 -0
- ansible_test/_internal/commands/integration/cloud/openshift.py +1 -0
- ansible_test/_internal/commands/integration/cloud/scaleway.py +1 -0
- ansible_test/_internal/commands/integration/cloud/vcenter.py +1 -0
- ansible_test/_internal/commands/integration/cloud/vultr.py +1 -0
- ansible_test/_internal/commands/integration/coverage.py +8 -2
- ansible_test/_internal/commands/integration/filters.py +1 -0
- ansible_test/_internal/commands/integration/network.py +1 -0
- ansible_test/_internal/commands/integration/posix.py +1 -0
- ansible_test/_internal/commands/integration/windows.py +1 -0
- ansible_test/_internal/commands/sanity/__init__.py +19 -2
- ansible_test/_internal/commands/sanity/ansible_doc.py +1 -0
- ansible_test/_internal/commands/sanity/bin_symlinks.py +1 -0
- ansible_test/_internal/commands/sanity/compile.py +1 -0
- ansible_test/_internal/commands/sanity/ignores.py +1 -0
- ansible_test/_internal/commands/sanity/import.py +1 -0
- ansible_test/_internal/commands/sanity/integration_aliases.py +12 -0
- ansible_test/_internal/commands/sanity/pep8.py +1 -0
- ansible_test/_internal/commands/sanity/pslint.py +1 -0
- ansible_test/_internal/commands/sanity/pylint.py +25 -26
- ansible_test/_internal/commands/sanity/shellcheck.py +1 -0
- ansible_test/_internal/commands/sanity/validate_modules.py +1 -0
- ansible_test/_internal/commands/sanity/yamllint.py +1 -0
- ansible_test/_internal/commands/shell/__init__.py +44 -4
- ansible_test/_internal/commands/units/__init__.py +5 -1
- ansible_test/_internal/compat/__init__.py +1 -0
- ansible_test/_internal/compat/packaging.py +1 -0
- ansible_test/_internal/compat/yaml.py +1 -0
- ansible_test/_internal/completion.py +1 -0
- ansible_test/_internal/config.py +23 -13
- ansible_test/_internal/connections.py +1 -0
- ansible_test/_internal/constants.py +1 -0
- ansible_test/_internal/containers.py +1 -0
- ansible_test/_internal/content_config.py +1 -0
- ansible_test/_internal/core_ci.py +1 -0
- ansible_test/_internal/coverage_util.py +11 -10
- ansible_test/_internal/data.py +1 -0
- ansible_test/_internal/debugging.py +166 -0
- ansible_test/_internal/delegation.py +22 -13
- ansible_test/_internal/dev/__init__.py +1 -0
- ansible_test/_internal/dev/container_probe.py +1 -0
- ansible_test/_internal/diff.py +3 -2
- ansible_test/_internal/docker_util.py +2 -1
- ansible_test/_internal/encoding.py +1 -0
- ansible_test/_internal/executor.py +1 -0
- ansible_test/_internal/git.py +1 -0
- ansible_test/_internal/host_configs.py +1 -0
- ansible_test/_internal/host_profiles.py +260 -16
- ansible_test/_internal/http.py +1 -0
- ansible_test/_internal/init.py +1 -0
- ansible_test/_internal/inventory.py +39 -3
- ansible_test/_internal/io.py +1 -0
- ansible_test/_internal/metadata.py +95 -4
- ansible_test/_internal/payload.py +1 -0
- ansible_test/_internal/processes.py +80 -0
- ansible_test/_internal/provider/__init__.py +1 -0
- ansible_test/_internal/provider/layout/__init__.py +1 -0
- ansible_test/_internal/provider/layout/ansible.py +1 -0
- ansible_test/_internal/provider/layout/collection.py +1 -0
- ansible_test/_internal/provider/layout/unsupported.py +1 -0
- ansible_test/_internal/provider/source/__init__.py +1 -0
- ansible_test/_internal/provider/source/git.py +1 -0
- ansible_test/_internal/provider/source/installed.py +1 -0
- ansible_test/_internal/provider/source/unsupported.py +1 -0
- ansible_test/_internal/provider/source/unversioned.py +1 -0
- ansible_test/_internal/provisioning.py +11 -4
- ansible_test/_internal/pypi_proxy.py +6 -5
- ansible_test/_internal/python_requirements.py +28 -0
- ansible_test/_internal/ssh.py +2 -5
- ansible_test/_internal/target.py +9 -0
- ansible_test/_internal/test.py +3 -2
- ansible_test/_internal/thread.py +3 -1
- ansible_test/_internal/timeout.py +2 -1
- ansible_test/_internal/util.py +41 -12
- ansible_test/_internal/util_common.py +18 -5
- ansible_test/_internal/venv.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/action-plugin-docs.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/changelog/sphinx.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/changelog.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/empty-init.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/line-endings.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-assert.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-get-exception.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-illegal-filenames.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-smart-quotes.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/replace-urlopen.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/runtime-metadata.py +28 -1
- ansible_test/_util/controller/sanity/code-smell/shebang.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/symlinks.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/use-argspec-type-path.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/use-compat-six.py +1 -0
- ansible_test/_util/controller/sanity/integration-aliases/yaml_to_json.py +2 -1
- ansible_test/_util/controller/sanity/pep8/current-ignore.txt +4 -0
- ansible_test/_util/controller/sanity/pylint/config/ansible-test-target.cfg +8 -5
- ansible_test/_util/controller/sanity/pylint/config/ansible-test.cfg +8 -5
- ansible_test/_util/controller/sanity/pylint/config/code-smell.cfg +8 -5
- ansible_test/_util/controller/sanity/pylint/config/collection.cfg +4 -5
- ansible_test/_util/controller/sanity/pylint/config/default.cfg +8 -7
- ansible_test/_util/controller/sanity/pylint/plugins/deprecated_calls.py +541 -0
- ansible_test/_util/controller/sanity/pylint/plugins/deprecated_comment.py +137 -0
- ansible_test/_util/controller/sanity/pylint/plugins/hide_unraisable.py +1 -0
- ansible_test/_util/controller/sanity/pylint/plugins/string_format.py +1 -8
- ansible_test/_util/controller/sanity/pylint/plugins/unwanted.py +1 -8
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py +55 -28
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/module_args.py +12 -5
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/schema.py +13 -2
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/utils.py +1 -0
- ansible_test/_util/controller/sanity/yamllint/yamllinter.py +35 -17
- ansible_test/_util/controller/tools/collection_detail.py +1 -0
- ansible_test/_util/controller/tools/yaml_to_json.py +2 -1
- ansible_test/_util/target/injector/python.py +8 -0
- ansible_test/_util/target/pytest/plugins/ansible_forked.py +6 -1
- ansible_test/_util/target/pytest/plugins/ansible_pytest_collections.py +2 -1
- ansible_test/_util/target/pytest/plugins/ansible_pytest_coverage.py +1 -0
- ansible_test/_util/target/sanity/compile/compile.py +1 -0
- ansible_test/_util/target/sanity/import/importer.py +15 -16
- ansible_test/_util/target/setup/bootstrap.sh +9 -20
- ansible_test/_util/target/setup/probe_cgroups.py +1 -0
- ansible_test/_util/target/setup/quiet_pip.py +1 -0
- ansible_test/_util/target/setup/requirements.py +38 -36
- ansible_test/_util/target/tools/virtualenvcheck.py +2 -1
- ansible_test/_util/target/tools/yamlcheck.py +2 -1
- ansible/compat/selectors.py +0 -32
- ansible/errors/yaml_strings.py +0 -138
- ansible/executor/action_write_locks.py +0 -44
- ansible/executor/discovery/python_target.py +0 -47
- ansible/executor/powershell/module_powershell_wrapper.ps1 +0 -86
- ansible/executor/powershell/module_script_wrapper.ps1 +0 -22
- ansible/module_utils/compat/importlib.py +0 -26
- ansible/module_utils/compat/selectors.py +0 -32
- ansible/module_utils/pycompat24.py +0 -73
- ansible/parsing/yaml/constructor.py +0 -178
- ansible/template/native_helpers.py +0 -251
- ansible/template/template.py +0 -43
- ansible/template/vars.py +0 -77
- ansible/utils/native_jinja.py +0 -11
- ansible/vars/fact_cache.py +0 -71
- ansible_core-2.18.7.dist-info/RECORD +0 -992
- ansible_test/_util/controller/sanity/pylint/plugins/deprecated.py +0 -411
- {ansible_core-2.18.7.dist-info → ansible_core-2.19.0.dist-info}/WHEEL +0 -0
- {ansible_core-2.18.7.dist-info → ansible_core-2.19.0.dist-info}/entry_points.txt +0 -0
- {ansible_core-2.18.7.dist-info → ansible_core-2.19.0.dist-info}/licenses/COPYING +0 -0
- {ansible_core-2.18.7.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/Apache-License.txt +0 -0
- {ansible_core-2.18.7.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/MIT-license.txt +0 -0
- {ansible_core-2.18.7.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/PSF-license.txt +0 -0
- {ansible_core-2.18.7.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/simplified_bsd.txt +0 -0
- {ansible_core-2.18.7.dist-info → ansible_core-2.19.0.dist-info}/top_level.txt +0 -0
ansible/vars/manager.py
CHANGED
|
@@ -19,38 +19,65 @@ from __future__ import annotations
|
|
|
19
19
|
|
|
20
20
|
import os
|
|
21
21
|
import sys
|
|
22
|
+
import typing as t
|
|
22
23
|
|
|
23
24
|
from collections import defaultdict
|
|
24
|
-
from collections.abc import Mapping, MutableMapping
|
|
25
|
-
from hashlib import sha1
|
|
26
|
-
|
|
27
|
-
from jinja2.exceptions import UndefinedError
|
|
25
|
+
from collections.abc import Mapping, MutableMapping
|
|
28
26
|
|
|
29
27
|
from ansible import constants as C
|
|
30
|
-
from ansible.
|
|
28
|
+
from ansible.module_utils._internal import _deprecator
|
|
29
|
+
from ansible.module_utils._internal._datatag import _tags
|
|
30
|
+
from ansible.errors import (AnsibleError, AnsibleParserError, AnsibleUndefinedVariable, AnsibleFileNotFound,
|
|
31
|
+
AnsibleAssertionError, AnsibleValueOmittedError)
|
|
31
32
|
from ansible.inventory.host import Host
|
|
32
33
|
from ansible.inventory.helpers import sort_groups, get_group_vars
|
|
33
|
-
from ansible.
|
|
34
|
+
from ansible.inventory.manager import InventoryManager
|
|
35
|
+
from ansible.module_utils.datatag import native_type_name
|
|
34
36
|
from ansible.module_utils.six import text_type
|
|
35
|
-
from ansible.
|
|
36
|
-
from ansible.
|
|
37
|
+
from ansible.parsing.dataloader import DataLoader
|
|
38
|
+
from ansible._internal._templating._engine import TemplateEngine
|
|
39
|
+
from ansible.plugins.loader import cache_loader
|
|
37
40
|
from ansible.utils.display import Display
|
|
38
41
|
from ansible.utils.vars import combine_vars, load_extra_vars, load_options_vars
|
|
39
|
-
from ansible.utils.unsafe_proxy import wrap_var
|
|
40
42
|
from ansible.vars.clean import namespace_facts, clean_facts
|
|
43
|
+
from ansible.vars.hostvars import HostVars
|
|
41
44
|
from ansible.vars.plugins import get_vars_from_inventory_sources, get_vars_from_path
|
|
42
45
|
from ansible.vars.reserved import warn_if_reserved
|
|
43
46
|
|
|
47
|
+
if t.TYPE_CHECKING:
|
|
48
|
+
from ansible.playbook import Play
|
|
49
|
+
from ansible.playbook.task import Task
|
|
50
|
+
|
|
44
51
|
display = Display()
|
|
45
52
|
|
|
53
|
+
# deprecated: description='enable top-level facts deprecation' core_version='2.20'
|
|
54
|
+
# _DEPRECATE_TOP_LEVEL_FACT_TAG = _tags.Deprecated(
|
|
55
|
+
# msg='Top-level facts are deprecated.',
|
|
56
|
+
# version='2.24',
|
|
57
|
+
# deprecator=_deprecator.ANSIBLE_CORE_DEPRECATOR,
|
|
58
|
+
# help_text='Use `ansible_facts` instead.',
|
|
59
|
+
# )
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _deprecate_top_level_fact(value: t.Any) -> t.Any:
|
|
63
|
+
"""
|
|
64
|
+
Deprecate the given top-level fact value.
|
|
65
|
+
The inner values are shared to aid in message de-duplication across hosts/values, and reduce intra-process memory usage.
|
|
66
|
+
Unique tag instances are required to achieve the correct de-duplication within a top-level templating operation.
|
|
67
|
+
"""
|
|
68
|
+
# deprecated: description='enable top-level facts deprecation' core_version='2.20'
|
|
69
|
+
# return _DEPRECATE_TOP_LEVEL_FACT_TAG.tag(value)
|
|
70
|
+
return value
|
|
71
|
+
|
|
46
72
|
|
|
47
73
|
def preprocess_vars(a):
|
|
48
|
-
|
|
74
|
+
"""
|
|
49
75
|
Ensures that vars contained in the parameter passed in are
|
|
50
76
|
returned as a list of dictionaries, to ensure for instance
|
|
51
77
|
that vars loaded from a file conform to an expected state.
|
|
52
|
-
|
|
78
|
+
"""
|
|
53
79
|
|
|
80
|
+
# FIXME: this does not properly handle omit, undefined, or dynamic structure from templated `vars` ; templating should be done earlier
|
|
54
81
|
if a is None:
|
|
55
82
|
return None
|
|
56
83
|
elif not isinstance(a, list):
|
|
@@ -60,7 +87,11 @@ def preprocess_vars(a):
|
|
|
60
87
|
|
|
61
88
|
for item in data:
|
|
62
89
|
if not isinstance(item, MutableMapping):
|
|
63
|
-
raise
|
|
90
|
+
raise AnsibleParserError(
|
|
91
|
+
message="Invalid variable file contents.",
|
|
92
|
+
obj=item,
|
|
93
|
+
help_text="Variable files must contain either a dictionary of variables, or a list of dictionaries.",
|
|
94
|
+
)
|
|
64
95
|
|
|
65
96
|
return data
|
|
66
97
|
|
|
@@ -70,16 +101,19 @@ class VariableManager:
|
|
|
70
101
|
_ALLOWED = frozenset(['plugins_by_group', 'groups_plugins_play', 'groups_plugins_inventory', 'groups_inventory',
|
|
71
102
|
'all_plugins_play', 'all_plugins_inventory', 'all_inventory'])
|
|
72
103
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
104
|
+
_PLAY_HOSTS_DEPRECATED_TAG = _tags.Deprecated(
|
|
105
|
+
msg='The `play_hosts` magic variable is deprecated.',
|
|
106
|
+
version='2.23',
|
|
107
|
+
deprecator=_deprecator.ANSIBLE_CORE_DEPRECATOR,
|
|
108
|
+
help_text='Use `ansible_play_batch` instead.',
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
def __init__(self, loader: DataLoader | None = None, inventory: InventoryManager | None = None, version_info: dict[str, str] | None = None) -> None:
|
|
112
|
+
self._nonpersistent_fact_cache: defaultdict[str, dict] = defaultdict(dict)
|
|
113
|
+
self._vars_cache: defaultdict[str, dict] = defaultdict(dict)
|
|
79
114
|
self._inventory = inventory
|
|
80
115
|
self._loader = loader
|
|
81
|
-
self._hostvars = None
|
|
82
|
-
self._omit_token = '__omit_place_holder__%s' % sha1(os.urandom(64)).hexdigest()
|
|
116
|
+
self._hostvars: HostVars | None = None
|
|
83
117
|
|
|
84
118
|
self._options_vars = load_options_vars(version_info)
|
|
85
119
|
|
|
@@ -93,41 +127,12 @@ class VariableManager:
|
|
|
93
127
|
|
|
94
128
|
# load fact cache
|
|
95
129
|
try:
|
|
96
|
-
self._fact_cache =
|
|
97
|
-
except
|
|
130
|
+
self._fact_cache = cache_loader.get(C.CACHE_PLUGIN)
|
|
131
|
+
except Exception as ex:
|
|
98
132
|
# bad cache plugin is not fatal error
|
|
99
|
-
# fallback to
|
|
100
|
-
display.
|
|
101
|
-
self._fact_cache =
|
|
102
|
-
|
|
103
|
-
def __getstate__(self):
|
|
104
|
-
data = dict(
|
|
105
|
-
fact_cache=self._fact_cache,
|
|
106
|
-
np_fact_cache=self._nonpersistent_fact_cache,
|
|
107
|
-
vars_cache=self._vars_cache,
|
|
108
|
-
extra_vars=self._extra_vars,
|
|
109
|
-
host_vars_files=self._host_vars_files,
|
|
110
|
-
group_vars_files=self._group_vars_files,
|
|
111
|
-
omit_token=self._omit_token,
|
|
112
|
-
options_vars=self._options_vars,
|
|
113
|
-
inventory=self._inventory,
|
|
114
|
-
safe_basedir=self.safe_basedir,
|
|
115
|
-
)
|
|
116
|
-
return data
|
|
117
|
-
|
|
118
|
-
def __setstate__(self, data):
|
|
119
|
-
self._fact_cache = data.get('fact_cache', defaultdict(dict))
|
|
120
|
-
self._nonpersistent_fact_cache = data.get('np_fact_cache', defaultdict(dict))
|
|
121
|
-
self._vars_cache = data.get('vars_cache', defaultdict(dict))
|
|
122
|
-
self._extra_vars = data.get('extra_vars', dict())
|
|
123
|
-
self._host_vars_files = data.get('host_vars_files', defaultdict(dict))
|
|
124
|
-
self._group_vars_files = data.get('group_vars_files', defaultdict(dict))
|
|
125
|
-
self._omit_token = data.get('omit_token', '__omit_place_holder__%s' % sha1(os.urandom(64)).hexdigest())
|
|
126
|
-
self._inventory = data.get('inventory', None)
|
|
127
|
-
self._options_vars = data.get('options_vars', dict())
|
|
128
|
-
self.safe_basedir = data.get('safe_basedir', False)
|
|
129
|
-
self._loader = None
|
|
130
|
-
self._hostvars = None
|
|
133
|
+
# fallback to builtin memory cache plugin
|
|
134
|
+
display.error_as_warning(None, ex)
|
|
135
|
+
self._fact_cache = cache_loader.get('ansible.builtin.memory') # use FQCN to ensure the builtin version is used
|
|
131
136
|
|
|
132
137
|
@property
|
|
133
138
|
def extra_vars(self):
|
|
@@ -136,9 +141,18 @@ class VariableManager:
|
|
|
136
141
|
def set_inventory(self, inventory):
|
|
137
142
|
self._inventory = inventory
|
|
138
143
|
|
|
139
|
-
def get_vars(
|
|
140
|
-
|
|
141
|
-
|
|
144
|
+
def get_vars(
|
|
145
|
+
self,
|
|
146
|
+
play: Play | None = None,
|
|
147
|
+
host: Host | None = None,
|
|
148
|
+
task: Task | None = None,
|
|
149
|
+
include_hostvars: bool = True,
|
|
150
|
+
use_cache: bool = True,
|
|
151
|
+
_hosts: list[str] | None = None,
|
|
152
|
+
_hosts_all: list[str] | None = None,
|
|
153
|
+
stage: str = 'task',
|
|
154
|
+
) -> dict[str, t.Any]:
|
|
155
|
+
"""
|
|
142
156
|
Returns the variables, with optional "context" given via the parameters
|
|
143
157
|
for the play, host, and task (which could possibly result in different
|
|
144
158
|
sets of variables being returned due to the additional context).
|
|
@@ -146,7 +160,6 @@ class VariableManager:
|
|
|
146
160
|
The order of precedence is:
|
|
147
161
|
- play->roles->get_default_vars (if there is a play context)
|
|
148
162
|
- group_vars_files[host] (if there is a host context)
|
|
149
|
-
- host_vars_files[host] (if there is a host context)
|
|
150
163
|
- host->get_vars (if there is a host context)
|
|
151
164
|
- fact_cache[host] (if there is a host context)
|
|
152
165
|
- play vars (if there is a play context)
|
|
@@ -159,16 +172,11 @@ class VariableManager:
|
|
|
159
172
|
``_hosts`` and ``_hosts_all`` should be considered private args, with only internal trusted callers relying
|
|
160
173
|
on the functionality they provide. These arguments may be removed at a later date without a deprecation
|
|
161
174
|
period and without warning.
|
|
162
|
-
|
|
163
|
-
if include_delegate_to:
|
|
164
|
-
display.deprecated(
|
|
165
|
-
"`VariableManager.get_vars`'s argument `include_delegate_to` has no longer any effect.",
|
|
166
|
-
version="2.19",
|
|
167
|
-
)
|
|
175
|
+
"""
|
|
168
176
|
|
|
169
177
|
display.debug("in VariableManager get_vars()")
|
|
170
178
|
|
|
171
|
-
all_vars = dict()
|
|
179
|
+
all_vars: dict[str, t.Any] = dict()
|
|
172
180
|
magic_variables = self._get_magic_variables(
|
|
173
181
|
play=play,
|
|
174
182
|
host=host,
|
|
@@ -178,21 +186,11 @@ class VariableManager:
|
|
|
178
186
|
_hosts_all=_hosts_all,
|
|
179
187
|
)
|
|
180
188
|
|
|
181
|
-
_vars_sources = {}
|
|
182
|
-
|
|
183
189
|
def _combine_and_track(data, new_data, source):
|
|
184
|
-
|
|
185
|
-
Wrapper function to update var sources dict and call combine_vars()
|
|
186
|
-
|
|
187
|
-
See notes in the VarsWithSources docstring for caveats and limitations of the source tracking
|
|
188
|
-
'''
|
|
190
|
+
# FIXME: this no longer does any tracking, only a slight optimization for empty new_data
|
|
189
191
|
if new_data == {}:
|
|
190
192
|
return data
|
|
191
193
|
|
|
192
|
-
if C.DEFAULT_DEBUG:
|
|
193
|
-
# Populate var sources dict
|
|
194
|
-
for key in new_data:
|
|
195
|
-
_vars_sources[key] = source
|
|
196
194
|
return combine_vars(data, new_data)
|
|
197
195
|
|
|
198
196
|
# default for all cases
|
|
@@ -226,33 +224,15 @@ class VariableManager:
|
|
|
226
224
|
if host:
|
|
227
225
|
# THE 'all' group and the rest of groups for a host, used below
|
|
228
226
|
all_group = self._inventory.groups.get('all')
|
|
229
|
-
host_groups = sort_groups([g for g in host.get_groups() if g.name
|
|
230
|
-
|
|
231
|
-
def _get_plugin_vars(plugin, path, entities):
|
|
232
|
-
data = {}
|
|
233
|
-
try:
|
|
234
|
-
data = plugin.get_vars(self._loader, path, entities)
|
|
235
|
-
except AttributeError:
|
|
236
|
-
try:
|
|
237
|
-
for entity in entities:
|
|
238
|
-
if isinstance(entity, Host):
|
|
239
|
-
data |= plugin.get_host_vars(entity.name)
|
|
240
|
-
else:
|
|
241
|
-
data |= plugin.get_group_vars(entity.name)
|
|
242
|
-
except AttributeError:
|
|
243
|
-
if hasattr(plugin, 'run'):
|
|
244
|
-
raise AnsibleError("Cannot use v1 type vars plugin %s from %s" % (plugin._load_name, plugin._original_path))
|
|
245
|
-
else:
|
|
246
|
-
raise AnsibleError("Invalid vars plugin %s from %s" % (plugin._load_name, plugin._original_path))
|
|
247
|
-
return data
|
|
227
|
+
host_groups = sort_groups([g for g in host.get_groups() if g.name != 'all'])
|
|
248
228
|
|
|
249
229
|
# internal functions that actually do the work
|
|
250
230
|
def _plugins_inventory(entities):
|
|
251
|
-
|
|
231
|
+
""" merges all entities by inventory source """
|
|
252
232
|
return get_vars_from_inventory_sources(self._loader, self._inventory._sources, entities, stage)
|
|
253
233
|
|
|
254
234
|
def _plugins_play(entities):
|
|
255
|
-
|
|
235
|
+
""" merges all entities adjacent to play """
|
|
256
236
|
data = {}
|
|
257
237
|
for path in basedirs:
|
|
258
238
|
data = _combine_and_track(data, get_vars_from_path(self._loader, path, entities, stage), "path '%s'" % path)
|
|
@@ -269,22 +249,22 @@ class VariableManager:
|
|
|
269
249
|
return _plugins_play([all_group])
|
|
270
250
|
|
|
271
251
|
def groups_inventory():
|
|
272
|
-
|
|
252
|
+
""" gets group vars from inventory """
|
|
273
253
|
return get_group_vars(host_groups)
|
|
274
254
|
|
|
275
255
|
def groups_plugins_inventory():
|
|
276
|
-
|
|
256
|
+
""" gets plugin sources from inventory for groups """
|
|
277
257
|
return _plugins_inventory(host_groups)
|
|
278
258
|
|
|
279
259
|
def groups_plugins_play():
|
|
280
|
-
|
|
260
|
+
""" gets plugin sources from play for groups """
|
|
281
261
|
return _plugins_play(host_groups)
|
|
282
262
|
|
|
283
263
|
def plugins_by_groups():
|
|
284
|
-
|
|
264
|
+
"""
|
|
285
265
|
merges all plugin sources by group,
|
|
286
266
|
This should be used instead, NOT in combination with the other groups_plugins* functions
|
|
287
|
-
|
|
267
|
+
"""
|
|
288
268
|
data = {}
|
|
289
269
|
for group in host_groups:
|
|
290
270
|
data[group] = _combine_and_track(data[group], _plugins_inventory(group), "inventory group_vars for '%s'" % group)
|
|
@@ -308,15 +288,20 @@ class VariableManager:
|
|
|
308
288
|
# finally, the facts caches for this host, if it exists
|
|
309
289
|
# TODO: cleaning of facts should eventually become part of taskresults instead of vars
|
|
310
290
|
try:
|
|
311
|
-
|
|
291
|
+
try:
|
|
292
|
+
facts = self._fact_cache.get(host.name)
|
|
293
|
+
except KeyError:
|
|
294
|
+
facts = {}
|
|
295
|
+
|
|
312
296
|
all_vars |= namespace_facts(facts)
|
|
313
297
|
|
|
314
298
|
# push facts to main namespace
|
|
315
299
|
if C.INJECT_FACTS_AS_VARS:
|
|
316
|
-
|
|
300
|
+
deprecated_facts_vars = {k: _deprecate_top_level_fact(v) for k, v in clean_facts(facts).items()}
|
|
301
|
+
all_vars = _combine_and_track(all_vars, deprecated_facts_vars, "facts")
|
|
317
302
|
else:
|
|
318
303
|
# always 'promote' ansible_local
|
|
319
|
-
all_vars = _combine_and_track(all_vars,
|
|
304
|
+
all_vars = _combine_and_track(all_vars, {'ansible_local': facts.get('ansible_local', {})}, "facts")
|
|
320
305
|
except KeyError:
|
|
321
306
|
pass
|
|
322
307
|
|
|
@@ -324,63 +309,68 @@ class VariableManager:
|
|
|
324
309
|
all_vars = _combine_and_track(all_vars, play.get_vars(), "play vars")
|
|
325
310
|
|
|
326
311
|
vars_files = play.get_vars_files()
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
except AnsibleParserError:
|
|
369
|
-
raise
|
|
370
|
-
except (UndefinedError, AnsibleUndefinedVariable):
|
|
371
|
-
if host is not None and self._fact_cache.get(host.name, dict()).get('module_setup') and task is not None:
|
|
372
|
-
raise AnsibleUndefinedVariable("an undefined variable was found when attempting to template the vars_files item '%s'"
|
|
373
|
-
% vars_file_item, obj=vars_file_item)
|
|
374
|
-
else:
|
|
375
|
-
# we do not have a full context here, and the missing variable could be because of that
|
|
376
|
-
# so just show a warning and continue
|
|
377
|
-
display.vvv("skipping vars_file '%s' due to an undefined variable" % vars_file_item)
|
|
312
|
+
|
|
313
|
+
for vars_file_item in vars_files:
|
|
314
|
+
# create a set of temporary vars here, which incorporate the extra
|
|
315
|
+
# and magic vars so we can properly template the vars_files entries
|
|
316
|
+
# NOTE: this makes them depend on host vars/facts so things like
|
|
317
|
+
# ansible_facts['os_distribution'] can be used, ala include_vars.
|
|
318
|
+
# Consider DEPRECATING this in the future, since we have include_vars ...
|
|
319
|
+
temp_vars = combine_vars(all_vars, self._extra_vars)
|
|
320
|
+
temp_vars = combine_vars(temp_vars, magic_variables)
|
|
321
|
+
templar = TemplateEngine(loader=self._loader, variables=temp_vars)
|
|
322
|
+
|
|
323
|
+
# we assume each item in the list is itself a list, as we
|
|
324
|
+
# support "conditional includes" for vars_files, which mimics
|
|
325
|
+
# the with_first_found mechanism.
|
|
326
|
+
vars_file_list = vars_file_item
|
|
327
|
+
if not isinstance(vars_file_list, list):
|
|
328
|
+
vars_file_list = [vars_file_list]
|
|
329
|
+
|
|
330
|
+
# now we iterate through the (potential) files, and break out
|
|
331
|
+
# as soon as we read one from the list. If none are found, we
|
|
332
|
+
# raise an error, which is silently ignored at this point.
|
|
333
|
+
try:
|
|
334
|
+
for vars_file in vars_file_list:
|
|
335
|
+
vars_file = templar.template(vars_file)
|
|
336
|
+
if not (isinstance(vars_file, str)):
|
|
337
|
+
raise AnsibleParserError(
|
|
338
|
+
message=f"Invalid `vars_files` value of type {native_type_name(vars_file)!r}.",
|
|
339
|
+
obj=vars_file,
|
|
340
|
+
help_text="A `vars_files` value should either be a string or list of strings.",
|
|
341
|
+
)
|
|
342
|
+
try:
|
|
343
|
+
play_search_stack = play.get_search_path()
|
|
344
|
+
found_file = self._loader.path_dwim_relative_stack(play_search_stack, 'vars', vars_file)
|
|
345
|
+
data = preprocess_vars(self._loader.load_from_file(found_file, unsafe=True, cache='vaulted', trusted_as_template=True))
|
|
346
|
+
if data is not None:
|
|
347
|
+
for item in data:
|
|
348
|
+
all_vars = _combine_and_track(all_vars, item, "play vars_files from '%s'" % vars_file)
|
|
349
|
+
display.vvv(f"Read `vars_file` {found_file!r}.")
|
|
350
|
+
break
|
|
351
|
+
except AnsibleFileNotFound:
|
|
352
|
+
# we continue on loader failures
|
|
378
353
|
continue
|
|
354
|
+
except AnsibleParserError:
|
|
355
|
+
raise
|
|
356
|
+
except AnsibleUndefinedVariable:
|
|
357
|
+
raise
|
|
358
|
+
except Exception as ex:
|
|
359
|
+
raise AnsibleParserError(f"Error reading `vars_files` file {vars_file!r}.", obj=vars_file) from ex
|
|
360
|
+
|
|
361
|
+
except AnsibleUndefinedVariable as ex:
|
|
362
|
+
if host is not None:
|
|
363
|
+
try:
|
|
364
|
+
facts = self._fact_cache.get(host.name)
|
|
365
|
+
except KeyError:
|
|
366
|
+
pass
|
|
367
|
+
else:
|
|
368
|
+
if facts.get('module_setup') and task is not None:
|
|
369
|
+
raise AnsibleUndefinedVariable("an undefined variable was found when attempting to template the vars_files item '%s'"
|
|
370
|
+
% vars_file_item, obj=vars_file_item) from ex
|
|
379
371
|
|
|
380
|
-
display.
|
|
381
|
-
|
|
382
|
-
raise AnsibleParserError("Error while reading vars files - please supply a list of file names. "
|
|
383
|
-
"Got '%s' of type %s" % (vars_files, type(vars_files)))
|
|
372
|
+
display.warning("skipping vars_file item due to an undefined variable", obj=vars_file_item)
|
|
373
|
+
continue
|
|
384
374
|
|
|
385
375
|
# We now merge in all exported vars from all roles in the play (very high precedence)
|
|
386
376
|
for role in play.roles:
|
|
@@ -417,7 +407,7 @@ class VariableManager:
|
|
|
417
407
|
all_vars = _combine_and_track(all_vars, self._extra_vars, "extra vars")
|
|
418
408
|
|
|
419
409
|
# before we add 'reserved vars', check we didn't add any reserved vars
|
|
420
|
-
warn_if_reserved(all_vars
|
|
410
|
+
warn_if_reserved(all_vars)
|
|
421
411
|
|
|
422
412
|
# magic variables
|
|
423
413
|
all_vars = _combine_and_track(all_vars, magic_variables, "magic vars")
|
|
@@ -433,17 +423,21 @@ class VariableManager:
|
|
|
433
423
|
all_vars['vars'] = all_vars.copy()
|
|
434
424
|
|
|
435
425
|
display.debug("done with get_vars()")
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
426
|
+
return all_vars
|
|
427
|
+
|
|
428
|
+
def _facts_gathered_for_host(self, hostname) -> bool:
|
|
429
|
+
try:
|
|
430
|
+
facts = self._fact_cache.get(hostname)
|
|
431
|
+
except KeyError:
|
|
432
|
+
facts = {}
|
|
433
|
+
|
|
434
|
+
return bool(facts.get('_ansible_facts_gathered', False))
|
|
441
435
|
|
|
442
436
|
def _get_magic_variables(self, play, host, task, include_hostvars, _hosts=None, _hosts_all=None):
|
|
443
|
-
|
|
437
|
+
"""
|
|
444
438
|
Returns a dictionary of so-called "magic" variables in Ansible,
|
|
445
439
|
which are special variables we set internally for use.
|
|
446
|
-
|
|
440
|
+
"""
|
|
447
441
|
|
|
448
442
|
variables = {}
|
|
449
443
|
variables['playbook_dir'] = os.path.abspath(self._loader.get_basedir())
|
|
@@ -480,13 +474,13 @@ class VariableManager:
|
|
|
480
474
|
if self._inventory is not None:
|
|
481
475
|
variables['groups'] = self._inventory.get_groups_dict()
|
|
482
476
|
if play:
|
|
483
|
-
templar = Templar(loader=self._loader)
|
|
484
|
-
if not play.finalized and templar.is_template(play.hosts):
|
|
485
|
-
pattern = 'all'
|
|
486
|
-
else:
|
|
487
|
-
pattern = play.hosts or 'all'
|
|
488
477
|
# add the list of hosts in the play, as adjusted for limit/filters
|
|
489
478
|
if not _hosts_all:
|
|
479
|
+
if not play.finalized and TemplateEngine().is_template(play.hosts):
|
|
480
|
+
pattern = 'all'
|
|
481
|
+
else:
|
|
482
|
+
pattern = play.hosts or 'all'
|
|
483
|
+
|
|
490
484
|
_hosts_all = [h.name for h in self._inventory.get_hosts(pattern=pattern, ignore_restrictions=True)]
|
|
491
485
|
if not _hosts:
|
|
492
486
|
_hosts = [h.name for h in self._inventory.get_hosts()]
|
|
@@ -495,12 +489,9 @@ class VariableManager:
|
|
|
495
489
|
variables['ansible_play_hosts'] = [x for x in variables['ansible_play_hosts_all'] if x not in play._removed_hosts]
|
|
496
490
|
variables['ansible_play_batch'] = [x for x in _hosts if x not in play._removed_hosts]
|
|
497
491
|
|
|
498
|
-
#
|
|
499
|
-
|
|
500
|
-
variables['play_hosts'] = variables['ansible_play_batch']
|
|
492
|
+
# use a static tag instead of `deprecate_value` to avoid stackwalk in a hot code path
|
|
493
|
+
variables['play_hosts'] = self._PLAY_HOSTS_DEPRECATED_TAG.tag(variables['ansible_play_batch'])
|
|
501
494
|
|
|
502
|
-
# the 'omit' value allows params to be left out if the variable they are based on is undefined
|
|
503
|
-
variables['omit'] = self._omit_token
|
|
504
495
|
# Set options vars
|
|
505
496
|
for option, option_value in self._options_vars.items():
|
|
506
497
|
variables[option] = option_value
|
|
@@ -517,56 +508,65 @@ class VariableManager:
|
|
|
517
508
|
Not used directly be VariableManager, but used primarily within TaskExecutor
|
|
518
509
|
"""
|
|
519
510
|
delegated_vars = {}
|
|
520
|
-
delegated_host_name = None
|
|
521
|
-
if task.delegate_to:
|
|
522
|
-
delegated_host_name = templar.template(task.delegate_to, fail_on_undefined=False)
|
|
511
|
+
delegated_host_name = ... # sentinel value distinct from empty/None, which are errors
|
|
523
512
|
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
513
|
+
if task.delegate_to:
|
|
514
|
+
try:
|
|
515
|
+
delegated_host_name = templar.template(task.delegate_to)
|
|
516
|
+
except AnsibleValueOmittedError:
|
|
517
|
+
pass
|
|
529
518
|
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
519
|
+
# bypass for unspecified value/omit
|
|
520
|
+
if delegated_host_name is ...:
|
|
521
|
+
return delegated_vars, None
|
|
522
|
+
|
|
523
|
+
if not delegated_host_name:
|
|
524
|
+
raise AnsibleError('Empty hostname produced from delegate_to: "%s"' % task.delegate_to)
|
|
525
|
+
|
|
526
|
+
delegated_host = self._inventory.get_host(delegated_host_name)
|
|
527
|
+
if delegated_host is None:
|
|
528
|
+
for h in self._inventory.get_hosts(ignore_limits=True, ignore_restrictions=True):
|
|
529
|
+
# check if the address matches, or if both the delegated_to host
|
|
530
|
+
# and the current host are in the list of localhost aliases
|
|
531
|
+
if h.address == delegated_host_name:
|
|
532
|
+
delegated_host = h
|
|
533
|
+
break
|
|
534
|
+
else:
|
|
535
|
+
delegated_host = Host(name=delegated_host_name)
|
|
536
|
+
|
|
537
|
+
delegated_vars['ansible_delegated_vars'] = {
|
|
538
|
+
delegated_host_name: self.get_vars(
|
|
539
|
+
play=task.get_play(),
|
|
540
|
+
host=delegated_host,
|
|
541
|
+
task=task,
|
|
542
|
+
include_hostvars=True,
|
|
543
|
+
)
|
|
544
|
+
}
|
|
545
|
+
delegated_vars['ansible_delegated_vars'][delegated_host_name]['inventory_hostname'] = variables.get('inventory_hostname')
|
|
550
546
|
|
|
551
547
|
return delegated_vars, delegated_host_name
|
|
552
548
|
|
|
553
549
|
def clear_facts(self, hostname):
|
|
554
|
-
|
|
550
|
+
"""
|
|
555
551
|
Clears the facts for a host
|
|
556
|
-
|
|
557
|
-
|
|
552
|
+
"""
|
|
553
|
+
try:
|
|
554
|
+
self._fact_cache.delete(hostname)
|
|
555
|
+
except KeyError:
|
|
556
|
+
pass
|
|
558
557
|
|
|
559
558
|
def set_host_facts(self, host, facts):
|
|
560
|
-
|
|
559
|
+
"""
|
|
561
560
|
Sets or updates the given facts for a host in the fact cache.
|
|
562
|
-
|
|
561
|
+
"""
|
|
563
562
|
|
|
564
563
|
if not isinstance(facts, Mapping):
|
|
565
564
|
raise AnsibleAssertionError("the type of 'facts' to set for host_facts should be a Mapping but is a %s" % type(facts))
|
|
566
565
|
|
|
567
|
-
warn_if_reserved(facts
|
|
566
|
+
warn_if_reserved(facts)
|
|
567
|
+
|
|
568
568
|
try:
|
|
569
|
-
host_cache = self._fact_cache
|
|
569
|
+
host_cache = self._fact_cache.get(host)
|
|
570
570
|
except KeyError:
|
|
571
571
|
# We get to set this as new
|
|
572
572
|
host_cache = facts
|
|
@@ -578,17 +578,18 @@ class VariableManager:
|
|
|
578
578
|
host_cache |= facts
|
|
579
579
|
|
|
580
580
|
# Save the facts back to the backing store
|
|
581
|
-
self._fact_cache
|
|
581
|
+
self._fact_cache.set(host, host_cache)
|
|
582
582
|
|
|
583
583
|
def set_nonpersistent_facts(self, host, facts):
|
|
584
|
-
|
|
584
|
+
"""
|
|
585
585
|
Sets or updates the given facts for a host in the fact cache.
|
|
586
|
-
|
|
586
|
+
"""
|
|
587
587
|
|
|
588
588
|
if not isinstance(facts, Mapping):
|
|
589
589
|
raise AnsibleAssertionError("the type of 'facts' to set for nonpersistent_facts should be a Mapping but is a %s" % type(facts))
|
|
590
590
|
|
|
591
|
-
warn_if_reserved(facts
|
|
591
|
+
warn_if_reserved(facts)
|
|
592
|
+
|
|
592
593
|
try:
|
|
593
594
|
self._nonpersistent_fact_cache[host] |= facts
|
|
594
595
|
except KeyError:
|
|
@@ -600,77 +601,11 @@ class VariableManager:
|
|
|
600
601
|
"""
|
|
601
602
|
|
|
602
603
|
warn_if_reserved([varname])
|
|
604
|
+
|
|
603
605
|
if host not in self._vars_cache:
|
|
604
606
|
self._vars_cache[host] = dict()
|
|
607
|
+
|
|
605
608
|
if varname in self._vars_cache[host] and isinstance(self._vars_cache[host][varname], MutableMapping) and isinstance(value, MutableMapping):
|
|
606
609
|
self._vars_cache[host] = combine_vars(self._vars_cache[host], {varname: value})
|
|
607
610
|
else:
|
|
608
611
|
self._vars_cache[host][varname] = value
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
class VarsWithSources(MutableMapping):
|
|
612
|
-
'''
|
|
613
|
-
Dict-like class for vars that also provides source information for each var
|
|
614
|
-
|
|
615
|
-
This class can only store the source for top-level vars. It does no tracking
|
|
616
|
-
on its own, just shows a debug message with the information that it is provided
|
|
617
|
-
when a particular var is accessed.
|
|
618
|
-
'''
|
|
619
|
-
def __init__(self, *args, **kwargs):
|
|
620
|
-
''' Dict-compatible constructor '''
|
|
621
|
-
self.data = dict(*args, **kwargs)
|
|
622
|
-
self.sources = {}
|
|
623
|
-
|
|
624
|
-
@classmethod
|
|
625
|
-
def new_vars_with_sources(cls, data, sources):
|
|
626
|
-
''' Alternate constructor method to instantiate class with sources '''
|
|
627
|
-
v = cls(data)
|
|
628
|
-
v.sources = sources
|
|
629
|
-
return v
|
|
630
|
-
|
|
631
|
-
def get_source(self, key):
|
|
632
|
-
return self.sources.get(key, None)
|
|
633
|
-
|
|
634
|
-
def __getitem__(self, key):
|
|
635
|
-
val = self.data[key]
|
|
636
|
-
# See notes in the VarsWithSources docstring for caveats and limitations of the source tracking
|
|
637
|
-
display.debug("variable '%s' from source: %s" % (key, self.sources.get(key, "unknown")))
|
|
638
|
-
return val
|
|
639
|
-
|
|
640
|
-
def __setitem__(self, key, value):
|
|
641
|
-
self.data[key] = value
|
|
642
|
-
|
|
643
|
-
def __delitem__(self, key):
|
|
644
|
-
del self.data[key]
|
|
645
|
-
|
|
646
|
-
def __iter__(self):
|
|
647
|
-
return iter(self.data)
|
|
648
|
-
|
|
649
|
-
def __len__(self):
|
|
650
|
-
return len(self.data)
|
|
651
|
-
|
|
652
|
-
# Prevent duplicate debug messages by defining our own __contains__ pointing at the underlying dict
|
|
653
|
-
def __contains__(self, key):
|
|
654
|
-
return self.data.__contains__(key)
|
|
655
|
-
|
|
656
|
-
def copy(self):
|
|
657
|
-
return VarsWithSources.new_vars_with_sources(self.data.copy(), self.sources.copy())
|
|
658
|
-
|
|
659
|
-
def __or__(self, other):
|
|
660
|
-
if isinstance(other, MutableMapping):
|
|
661
|
-
c = self.data.copy()
|
|
662
|
-
c.update(other)
|
|
663
|
-
return c
|
|
664
|
-
return NotImplemented
|
|
665
|
-
|
|
666
|
-
def __ror__(self, other):
|
|
667
|
-
if isinstance(other, MutableMapping):
|
|
668
|
-
c = self.__class__()
|
|
669
|
-
c.update(other)
|
|
670
|
-
c.update(self.data)
|
|
671
|
-
return c
|
|
672
|
-
return NotImplemented
|
|
673
|
-
|
|
674
|
-
def __ior__(self, other):
|
|
675
|
-
self.data.update(other)
|
|
676
|
-
return self.data
|