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