ansible-core 2.18.4rc1__py3-none-any.whl → 2.19.0b1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ansible/_internal/__init__.py +53 -0
- ansible/_internal/_ansiballz.py +265 -0
- ansible/_internal/_datatag/__init__.py +0 -0
- ansible/_internal/_datatag/_tags.py +130 -0
- ansible/_internal/_datatag/_utils.py +19 -0
- ansible/_internal/_datatag/_wrappers.py +33 -0
- ansible/_internal/_errors/__init__.py +0 -0
- ansible/_internal/_errors/_captured.py +128 -0
- ansible/_internal/_errors/_handler.py +91 -0
- ansible/_internal/_errors/_utils.py +310 -0
- ansible/_internal/_json/__init__.py +160 -0
- ansible/_internal/_json/_legacy_encoder.py +34 -0
- ansible/_internal/_json/_profiles/__init__.py +0 -0
- ansible/_internal/_json/_profiles/_cache_persistence.py +55 -0
- ansible/_internal/_json/_profiles/_inventory_legacy.py +40 -0
- ansible/_internal/_json/_profiles/_legacy.py +198 -0
- ansible/_internal/_locking.py +21 -0
- ansible/_internal/_plugins/__init__.py +0 -0
- ansible/_internal/_plugins/_cache.py +57 -0
- ansible/_internal/_task.py +78 -0
- ansible/_internal/_templating/__init__.py +10 -0
- ansible/_internal/_templating/_access.py +86 -0
- ansible/_internal/_templating/_chain_templar.py +63 -0
- ansible/_internal/_templating/_datatag.py +95 -0
- ansible/_internal/_templating/_engine.py +588 -0
- ansible/_internal/_templating/_errors.py +28 -0
- ansible/_internal/_templating/_jinja_bits.py +1066 -0
- ansible/_internal/_templating/_jinja_common.py +332 -0
- ansible/_internal/_templating/_jinja_patches.py +44 -0
- ansible/_internal/_templating/_jinja_plugins.py +351 -0
- ansible/_internal/_templating/_lazy_containers.py +633 -0
- ansible/_internal/_templating/_marker_behaviors.py +103 -0
- ansible/_internal/_templating/_transform.py +63 -0
- ansible/_internal/_templating/_utils.py +107 -0
- ansible/_internal/_wrapt.py +1052 -0
- ansible/_internal/_yaml/__init__.py +0 -0
- ansible/_internal/_yaml/_constructor.py +240 -0
- ansible/_internal/_yaml/_dumper.py +62 -0
- ansible/_internal/_yaml/_errors.py +166 -0
- ansible/_internal/_yaml/_loader.py +66 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/README.md +11 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/action/debug.py +36 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/apply_trust.py +19 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/dump_object.py +18 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/finalize.py +16 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/origin.py +18 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/python_literal_eval.py +24 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/python_literal_eval.yml +33 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/tag_names.py +16 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/true_type.py +17 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/unmask.py +49 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/lookup/config.py +21 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/lookup/config.yml +2 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged.py +15 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged.yml +19 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged_with.py +18 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged_with.yml +19 -0
- ansible/cli/__init__.py +153 -89
- ansible/cli/_ssh_askpass.py +47 -0
- ansible/cli/adhoc.py +14 -7
- ansible/cli/arguments/option_helpers.py +154 -7
- ansible/cli/config.py +43 -68
- ansible/cli/console.py +10 -8
- ansible/cli/doc.py +48 -46
- ansible/cli/galaxy.py +27 -20
- ansible/cli/inventory.py +28 -26
- ansible/cli/playbook.py +4 -12
- ansible/cli/pull.py +51 -11
- ansible/cli/scripts/ansible_connection_cli_stub.py +7 -7
- ansible/cli/vault.py +12 -11
- ansible/compat/__init__.py +2 -2
- ansible/config/base.yml +165 -108
- ansible/config/manager.py +52 -49
- ansible/constants.py +3 -4
- ansible/errors/__init__.py +277 -235
- ansible/executor/interpreter_discovery.py +28 -149
- ansible/executor/module_common.py +426 -493
- ansible/executor/play_iterator.py +22 -27
- ansible/executor/playbook_executor.py +11 -11
- ansible/executor/powershell/async_watchdog.ps1 +97 -102
- ansible/executor/powershell/async_wrapper.ps1 +202 -151
- ansible/executor/powershell/become_wrapper.ps1 +89 -144
- ansible/executor/powershell/bootstrap_wrapper.ps1 +24 -9
- ansible/executor/powershell/coverage_wrapper.ps1 +82 -135
- ansible/executor/powershell/exec_wrapper.ps1 +462 -196
- ansible/executor/powershell/module_manifest.py +417 -265
- ansible/executor/powershell/module_wrapper.ps1 +169 -186
- ansible/executor/powershell/psrp_fetch_file.ps1 +41 -0
- ansible/executor/powershell/psrp_put_file.ps1 +122 -0
- ansible/executor/powershell/winrm_fetch_file.ps1 +46 -0
- ansible/executor/powershell/winrm_put_file.ps1 +36 -0
- ansible/executor/process/worker.py +136 -76
- ansible/executor/stats.py +5 -5
- ansible/executor/task_executor.py +237 -236
- ansible/executor/task_queue_manager.py +62 -38
- ansible/executor/task_result.py +21 -12
- ansible/galaxy/__init__.py +2 -2
- ansible/galaxy/api.py +22 -18
- ansible/galaxy/collection/__init__.py +1 -1
- ansible/galaxy/collection/concrete_artifact_manager.py +8 -11
- ansible/galaxy/dependency_resolution/dataclasses.py +14 -4
- ansible/galaxy/dependency_resolution/providers.py +1 -1
- ansible/galaxy/dependency_resolution/reporters.py +81 -0
- ansible/galaxy/role.py +4 -8
- ansible/galaxy/token.py +28 -21
- ansible/inventory/data.py +47 -57
- ansible/inventory/group.py +44 -72
- ansible/inventory/helpers.py +9 -0
- ansible/inventory/host.py +32 -54
- ansible/inventory/manager.py +77 -34
- ansible/keyword_desc.yml +1 -1
- ansible/module_utils/_internal/__init__.py +55 -0
- ansible/module_utils/_internal/_ambient_context.py +58 -0
- ansible/module_utils/_internal/_ansiballz.py +133 -0
- ansible/module_utils/_internal/_concurrent/_daemon_threading.py +1 -0
- ansible/module_utils/_internal/_dataclass_annotation_patch.py +64 -0
- ansible/module_utils/_internal/_dataclass_validation.py +217 -0
- ansible/module_utils/_internal/_datatag/__init__.py +928 -0
- ansible/module_utils/_internal/_datatag/_tags.py +38 -0
- ansible/module_utils/_internal/_debugging.py +31 -0
- ansible/module_utils/_internal/_errors.py +30 -0
- ansible/module_utils/_internal/_json/__init__.py +63 -0
- ansible/module_utils/_internal/_json/_legacy_encoder.py +26 -0
- ansible/module_utils/_internal/_json/_profiles/__init__.py +410 -0
- ansible/module_utils/_internal/_json/_profiles/_fallback_to_str.py +73 -0
- ansible/module_utils/_internal/_json/_profiles/_module_legacy_c2m.py +31 -0
- ansible/module_utils/_internal/_json/_profiles/_module_legacy_m2c.py +35 -0
- ansible/module_utils/_internal/_json/_profiles/_module_modern_c2m.py +35 -0
- ansible/module_utils/_internal/_json/_profiles/_module_modern_m2c.py +33 -0
- ansible/module_utils/_internal/_json/_profiles/_tagless.py +50 -0
- ansible/module_utils/_internal/_patches/__init__.py +66 -0
- ansible/module_utils/_internal/_patches/_dataclass_annotation_patch.py +55 -0
- ansible/module_utils/_internal/_patches/_socket_patch.py +34 -0
- ansible/module_utils/_internal/_patches/_sys_intern_patch.py +34 -0
- ansible/module_utils/_internal/_plugin_exec_context.py +49 -0
- ansible/module_utils/_internal/_testing.py +0 -0
- ansible/module_utils/_internal/_traceback.py +89 -0
- ansible/module_utils/ansible_release.py +2 -2
- ansible/module_utils/api.py +1 -2
- ansible/module_utils/basic.py +154 -120
- ansible/module_utils/common/_utils.py +24 -28
- ansible/module_utils/common/collections.py +1 -2
- ansible/module_utils/common/dict_transformations.py +2 -2
- ansible/module_utils/common/file.py +2 -2
- ansible/module_utils/common/json.py +90 -84
- ansible/module_utils/common/locale.py +2 -2
- ansible/module_utils/common/messages.py +108 -0
- ansible/module_utils/common/parameters.py +27 -24
- ansible/module_utils/common/process.py +2 -2
- ansible/module_utils/common/respawn.py +41 -19
- ansible/module_utils/common/sentinel.py +66 -0
- ansible/module_utils/common/sys_info.py +8 -8
- ansible/module_utils/common/text/converters.py +16 -37
- ansible/module_utils/common/validation.py +35 -24
- ansible/module_utils/common/warnings.py +86 -25
- ansible/module_utils/common/yaml.py +29 -3
- ansible/module_utils/compat/datetime.py +33 -21
- ansible/module_utils/compat/paramiko.py +21 -10
- ansible/module_utils/compat/typing.py +6 -5
- ansible/module_utils/connection.py +2 -2
- ansible/module_utils/csharp/Ansible.Basic.cs +14 -11
- ansible/module_utils/csharp/Ansible.Become.cs +1 -0
- ansible/module_utils/csharp/Ansible._Async.cs +517 -0
- ansible/module_utils/datatag.py +46 -0
- ansible/module_utils/distro/__init__.py +2 -2
- ansible/module_utils/facts/ansible_collector.py +4 -5
- ansible/module_utils/facts/collector.py +13 -14
- ansible/module_utils/facts/compat.py +4 -4
- ansible/module_utils/facts/default_collectors.py +1 -1
- ansible/module_utils/facts/hardware/aix.py +34 -0
- ansible/module_utils/facts/hardware/base.py +1 -1
- ansible/module_utils/facts/hardware/darwin.py +1 -3
- ansible/module_utils/facts/hardware/freebsd.py +2 -2
- ansible/module_utils/facts/hardware/linux.py +4 -4
- ansible/module_utils/facts/namespace.py +1 -1
- ansible/module_utils/facts/network/base.py +1 -1
- ansible/module_utils/facts/network/fc_wwn.py +1 -2
- ansible/module_utils/facts/network/iscsi.py +1 -2
- ansible/module_utils/facts/network/nvme.py +1 -2
- ansible/module_utils/facts/other/facter.py +1 -2
- ansible/module_utils/facts/other/ohai.py +2 -3
- ansible/module_utils/facts/system/apparmor.py +1 -2
- ansible/module_utils/facts/system/caps.py +1 -1
- ansible/module_utils/facts/system/chroot.py +1 -2
- ansible/module_utils/facts/system/cmdline.py +1 -2
- ansible/module_utils/facts/system/date_time.py +5 -3
- ansible/module_utils/facts/system/distribution.py +9 -8
- ansible/module_utils/facts/system/dns.py +1 -1
- ansible/module_utils/facts/system/env.py +1 -2
- ansible/module_utils/facts/system/fips.py +7 -20
- ansible/module_utils/facts/system/loadavg.py +1 -2
- ansible/module_utils/facts/system/local.py +1 -2
- ansible/module_utils/facts/system/lsb.py +1 -2
- ansible/module_utils/facts/system/pkg_mgr.py +1 -2
- ansible/module_utils/facts/system/platform.py +1 -2
- ansible/module_utils/facts/system/python.py +1 -2
- ansible/module_utils/facts/system/selinux.py +1 -1
- ansible/module_utils/facts/system/service_mgr.py +1 -2
- ansible/module_utils/facts/system/ssh_pub_keys.py +1 -1
- ansible/module_utils/facts/system/systemd.py +1 -1
- ansible/module_utils/facts/system/user.py +1 -2
- ansible/module_utils/facts/utils.py +3 -3
- ansible/module_utils/facts/virtual/base.py +1 -1
- ansible/module_utils/facts/virtual/sunos.py +3 -15
- ansible/module_utils/facts/virtual/sysctl.py +3 -16
- ansible/module_utils/json_utils.py +2 -2
- ansible/module_utils/parsing/convert_bool.py +1 -1
- ansible/module_utils/service.py +18 -21
- ansible/module_utils/splitter.py +7 -7
- ansible/module_utils/testing.py +31 -0
- ansible/module_utils/urls.py +60 -31
- ansible/modules/add_host.py +4 -4
- ansible/modules/apt.py +60 -46
- ansible/modules/apt_key.py +19 -12
- ansible/modules/apt_repository.py +19 -16
- ansible/modules/assemble.py +6 -6
- ansible/modules/assert.py +4 -4
- ansible/modules/async_status.py +10 -12
- ansible/modules/async_wrapper.py +8 -3
- ansible/modules/blockinfile.py +6 -7
- ansible/modules/command.py +10 -17
- ansible/modules/copy.py +57 -144
- ansible/modules/cron.py +20 -15
- ansible/modules/deb822_repository.py +8 -9
- ansible/modules/debconf.py +5 -5
- ansible/modules/debug.py +4 -4
- ansible/modules/dnf.py +8 -8
- ansible/modules/dnf5.py +52 -17
- 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 +20 -18
- 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 +7 -7
- 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 +35 -49
- ansible/modules/user.py +53 -34
- ansible/modules/validate_argument_spec.py +10 -7
- ansible/modules/wait_for.py +39 -32
- ansible/modules/wait_for_connection.py +6 -6
- ansible/modules/yum_repository.py +6 -6
- ansible/parsing/ajson.py +14 -32
- ansible/parsing/dataloader.py +99 -54
- ansible/parsing/mod_args.py +28 -44
- ansible/parsing/plugin_docs.py +21 -86
- ansible/parsing/quoting.py +1 -1
- ansible/parsing/splitter.py +27 -12
- ansible/parsing/utils/addresses.py +24 -24
- ansible/parsing/utils/yaml.py +32 -61
- ansible/parsing/vault/__init__.py +319 -87
- ansible/parsing/yaml/__init__.py +0 -18
- ansible/parsing/yaml/dumper.py +6 -120
- ansible/parsing/yaml/loader.py +6 -39
- ansible/parsing/yaml/objects.py +36 -339
- ansible/playbook/__init__.py +1 -1
- ansible/playbook/attribute.py +8 -3
- ansible/playbook/base.py +182 -132
- ansible/playbook/block.py +26 -24
- ansible/playbook/collectionsearch.py +1 -15
- ansible/playbook/conditional.py +3 -77
- ansible/playbook/handler.py +8 -2
- ansible/playbook/helpers.py +41 -53
- ansible/playbook/included_file.py +6 -15
- ansible/playbook/loop_control.py +2 -2
- ansible/playbook/play.py +85 -44
- ansible/playbook/play_context.py +12 -17
- ansible/playbook/playbook_include.py +14 -15
- ansible/playbook/role/__init__.py +24 -26
- ansible/playbook/role/definition.py +15 -17
- ansible/playbook/role/include.py +2 -4
- ansible/playbook/role/metadata.py +10 -11
- ansible/playbook/role_include.py +3 -3
- ansible/playbook/taggable.py +13 -8
- ansible/playbook/task.py +188 -118
- ansible/playbook/task_include.py +5 -5
- ansible/plugins/__init__.py +68 -21
- ansible/plugins/action/__init__.py +209 -176
- ansible/plugins/action/add_host.py +1 -1
- ansible/plugins/action/assemble.py +1 -1
- ansible/plugins/action/assert.py +54 -66
- ansible/plugins/action/copy.py +7 -11
- ansible/plugins/action/debug.py +37 -31
- ansible/plugins/action/dnf.py +3 -4
- ansible/plugins/action/fail.py +1 -1
- ansible/plugins/action/fetch.py +4 -5
- ansible/plugins/action/gather_facts.py +8 -7
- ansible/plugins/action/group_by.py +1 -1
- ansible/plugins/action/include_vars.py +10 -11
- ansible/plugins/action/package.py +3 -6
- ansible/plugins/action/pause.py +2 -2
- ansible/plugins/action/script.py +15 -8
- ansible/plugins/action/service.py +6 -11
- ansible/plugins/action/set_fact.py +3 -12
- ansible/plugins/action/set_stats.py +3 -8
- ansible/plugins/action/template.py +35 -59
- ansible/plugins/action/unarchive.py +1 -1
- ansible/plugins/action/validate_argument_spec.py +5 -5
- ansible/plugins/action/wait_for_connection.py +1 -1
- ansible/plugins/become/__init__.py +31 -8
- ansible/plugins/become/runas.py +71 -0
- ansible/plugins/become/su.py +13 -8
- ansible/plugins/become/sudo.py +19 -0
- ansible/plugins/cache/__init__.py +35 -44
- ansible/plugins/cache/base.py +8 -0
- ansible/plugins/cache/jsonfile.py +10 -16
- ansible/plugins/cache/memory.py +6 -12
- ansible/plugins/callback/__init__.py +141 -123
- ansible/plugins/callback/default.py +30 -23
- ansible/plugins/callback/junit.py +28 -24
- ansible/plugins/callback/minimal.py +17 -14
- ansible/plugins/callback/oneline.py +13 -7
- ansible/plugins/callback/tree.py +10 -6
- ansible/plugins/connection/__init__.py +47 -34
- ansible/plugins/connection/local.py +150 -54
- ansible/plugins/connection/paramiko_ssh.py +21 -18
- ansible/plugins/connection/psrp.py +76 -165
- ansible/plugins/connection/ssh.py +301 -78
- ansible/plugins/connection/winrm.py +58 -140
- ansible/plugins/doc_fragments/action_common_attributes.py +14 -14
- ansible/plugins/doc_fragments/action_core.py +6 -6
- ansible/plugins/doc_fragments/backup.py +2 -2
- ansible/plugins/doc_fragments/checksum_common.py +27 -0
- ansible/plugins/doc_fragments/constructed.py +6 -2
- ansible/plugins/doc_fragments/decrypt.py +2 -2
- ansible/plugins/doc_fragments/default_callback.py +2 -2
- ansible/plugins/doc_fragments/files.py +2 -2
- ansible/plugins/doc_fragments/inventory_cache.py +2 -2
- ansible/plugins/doc_fragments/result_format_callback.py +2 -2
- ansible/plugins/doc_fragments/return_common.py +2 -2
- ansible/plugins/doc_fragments/template_common.py +4 -4
- ansible/plugins/doc_fragments/url.py +17 -1
- ansible/plugins/doc_fragments/url_windows.py +2 -2
- ansible/plugins/doc_fragments/validate.py +2 -2
- ansible/plugins/doc_fragments/vars_plugin_staging.py +2 -2
- ansible/plugins/filter/__init__.py +6 -2
- ansible/plugins/filter/b64decode.yml +22 -0
- ansible/plugins/filter/b64encode.yml +22 -0
- ansible/plugins/filter/bool.yml +11 -4
- ansible/plugins/filter/core.py +218 -108
- ansible/plugins/filter/encryption.py +32 -32
- ansible/plugins/filter/flatten.yml +3 -2
- ansible/plugins/filter/human_to_bytes.yml +2 -2
- ansible/plugins/filter/mathstuff.py +30 -37
- ansible/plugins/filter/password_hash.yml +8 -0
- ansible/plugins/filter/regex_search.yml +1 -4
- ansible/plugins/filter/split.yml +1 -1
- ansible/plugins/filter/to_nice_yaml.yml +0 -4
- ansible/plugins/filter/to_yaml.yml +0 -4
- ansible/plugins/filter/unvault.yml +1 -1
- ansible/plugins/filter/urls.py +1 -1
- ansible/plugins/filter/urlsplit.py +8 -9
- ansible/plugins/filter/vault.yml +14 -9
- ansible/plugins/filter/win_basename.yml +6 -1
- ansible/plugins/filter/win_dirname.yml +5 -0
- ansible/plugins/inventory/__init__.py +97 -77
- ansible/plugins/inventory/advanced_host_list.py +7 -5
- ansible/plugins/inventory/auto.py +11 -4
- ansible/plugins/inventory/constructed.py +21 -24
- ansible/plugins/inventory/generator.py +16 -11
- ansible/plugins/inventory/host_list.py +7 -5
- ansible/plugins/inventory/ini.py +78 -44
- ansible/plugins/inventory/script.py +189 -119
- ansible/plugins/inventory/toml.py +16 -126
- ansible/plugins/inventory/yaml.py +10 -8
- ansible/plugins/list.py +3 -3
- ansible/plugins/loader.py +197 -82
- ansible/plugins/lookup/__init__.py +21 -4
- ansible/plugins/lookup/config.py +21 -35
- ansible/plugins/lookup/csvfile.py +3 -2
- ansible/plugins/lookup/dict.py +1 -6
- ansible/plugins/lookup/env.py +12 -9
- ansible/plugins/lookup/file.py +5 -8
- ansible/plugins/lookup/first_found.py +86 -55
- ansible/plugins/lookup/indexed_items.py +1 -10
- ansible/plugins/lookup/ini.py +14 -13
- ansible/plugins/lookup/items.py +1 -1
- ansible/plugins/lookup/lines.py +8 -1
- ansible/plugins/lookup/list.py +1 -1
- ansible/plugins/lookup/nested.py +2 -18
- ansible/plugins/lookup/password.py +5 -5
- ansible/plugins/lookup/pipe.py +5 -7
- ansible/plugins/lookup/sequence.py +18 -8
- ansible/plugins/lookup/subelements.py +1 -4
- ansible/plugins/lookup/template.py +42 -36
- ansible/plugins/lookup/together.py +0 -12
- ansible/plugins/lookup/unvault.py +1 -5
- ansible/plugins/lookup/url.py +2 -8
- ansible/plugins/lookup/vars.py +16 -24
- ansible/plugins/shell/__init__.py +2 -2
- ansible/plugins/shell/cmd.py +2 -2
- ansible/plugins/shell/powershell.py +39 -22
- ansible/plugins/shell/sh.py +3 -2
- ansible/plugins/strategy/__init__.py +94 -113
- ansible/plugins/strategy/debug.py +2 -2
- ansible/plugins/strategy/free.py +13 -28
- ansible/plugins/strategy/host_pinned.py +2 -2
- ansible/plugins/strategy/linear.py +31 -33
- ansible/plugins/terminal/__init__.py +4 -4
- ansible/plugins/test/__init__.py +7 -2
- ansible/plugins/test/core.py +54 -20
- ansible/plugins/test/files.py +1 -1
- ansible/plugins/test/mathstuff.py +3 -3
- ansible/plugins/test/uri.py +3 -3
- ansible/plugins/vars/host_group_vars.py +7 -14
- ansible/release.py +2 -2
- ansible/template/__init__.py +368 -944
- ansible/utils/__init__.py +0 -18
- ansible/utils/_ssh_agent.py +657 -0
- ansible/utils/collection_loader/__init__.py +52 -5
- ansible/utils/collection_loader/_collection_config.py +5 -6
- ansible/utils/collection_loader/_collection_finder.py +79 -93
- ansible/utils/collection_loader/_collection_meta.py +13 -8
- ansible/utils/display.py +428 -58
- ansible/utils/encrypt.py +27 -19
- ansible/utils/fqcn.py +2 -2
- ansible/utils/hashing.py +2 -2
- ansible/utils/helpers.py +2 -2
- ansible/utils/listify.py +8 -8
- ansible/utils/lock.py +2 -2
- ansible/utils/path.py +4 -4
- ansible/utils/plugin_docs.py +14 -13
- ansible/utils/sentinel.py +4 -62
- ansible/utils/singleton.py +2 -0
- ansible/utils/ssh_functions.py +1 -1
- ansible/utils/unsafe_proxy.py +23 -332
- ansible/utils/vars.py +28 -8
- ansible/utils/version.py +2 -2
- ansible/vars/clean.py +4 -4
- ansible/vars/hostvars.py +60 -90
- ansible/vars/manager.py +205 -264
- ansible/vars/reserved.py +8 -9
- ansible_core-2.19.0b1.dist-info/BSD-3-Clause.txt +28 -0
- {ansible_core-2.18.4rc1.dist-info → ansible_core-2.19.0b1.dist-info}/METADATA +5 -4
- ansible_core-2.19.0b1.dist-info/RECORD +1070 -0
- {ansible_core-2.18.4rc1.dist-info → ansible_core-2.19.0b1.dist-info}/WHEEL +1 -1
- ansible_test/_data/completion/docker.txt +7 -7
- ansible_test/_data/completion/remote.txt +6 -6
- ansible_test/_data/completion/windows.txt +1 -0
- ansible_test/_data/requirements/ansible.txt +2 -2
- ansible_test/_data/requirements/sanity.ansible-doc.txt +3 -3
- ansible_test/_data/requirements/sanity.changelog.txt +1 -1
- ansible_test/_data/requirements/sanity.import.plugin.txt +2 -2
- ansible_test/_data/requirements/sanity.pylint.txt +4 -4
- ansible_test/_data/requirements/sanity.validate-modules.txt +2 -2
- ansible_test/_data/requirements/sanity.yamllint.txt +1 -1
- ansible_test/_data/requirements/units.txt +1 -0
- ansible_test/_internal/__init__.py +1 -0
- ansible_test/_internal/ansible_util.py +2 -0
- ansible_test/_internal/become.py +1 -0
- ansible_test/_internal/bootstrap.py +1 -0
- ansible_test/_internal/cache.py +1 -0
- ansible_test/_internal/cgroup.py +1 -0
- ansible_test/_internal/ci/__init__.py +1 -0
- ansible_test/_internal/ci/azp.py +1 -0
- ansible_test/_internal/ci/local.py +1 -0
- ansible_test/_internal/classification/__init__.py +1 -0
- ansible_test/_internal/classification/common.py +1 -0
- ansible_test/_internal/classification/csharp.py +1 -0
- ansible_test/_internal/classification/powershell.py +1 -0
- ansible_test/_internal/classification/python.py +1 -0
- ansible_test/_internal/cli/__init__.py +1 -0
- ansible_test/_internal/cli/actions.py +1 -0
- ansible_test/_internal/cli/argparsing/__init__.py +1 -0
- ansible_test/_internal/cli/argparsing/actions.py +1 -0
- ansible_test/_internal/cli/argparsing/argcompletion.py +1 -0
- ansible_test/_internal/cli/argparsing/parsers.py +1 -0
- ansible_test/_internal/cli/commands/__init__.py +11 -0
- ansible_test/_internal/cli/commands/coverage/__init__.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/__init__.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/__init__.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/combine.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/expand.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/filter.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/generate.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/missing.py +1 -0
- ansible_test/_internal/cli/commands/coverage/combine.py +1 -0
- ansible_test/_internal/cli/commands/coverage/erase.py +1 -0
- ansible_test/_internal/cli/commands/coverage/html.py +1 -0
- ansible_test/_internal/cli/commands/coverage/report.py +1 -0
- ansible_test/_internal/cli/commands/coverage/xml.py +1 -0
- ansible_test/_internal/cli/commands/env.py +1 -0
- ansible_test/_internal/cli/commands/integration/__init__.py +1 -0
- ansible_test/_internal/cli/commands/integration/network.py +1 -0
- ansible_test/_internal/cli/commands/integration/posix.py +1 -0
- ansible_test/_internal/cli/commands/integration/windows.py +1 -0
- ansible_test/_internal/cli/commands/sanity.py +9 -0
- ansible_test/_internal/cli/commands/shell.py +1 -0
- ansible_test/_internal/cli/commands/units.py +1 -0
- ansible_test/_internal/cli/compat.py +1 -0
- ansible_test/_internal/cli/completers.py +1 -0
- ansible_test/_internal/cli/converters.py +1 -0
- ansible_test/_internal/cli/environments.py +1 -0
- ansible_test/_internal/cli/epilog.py +1 -0
- ansible_test/_internal/cli/parsers/__init__.py +1 -0
- ansible_test/_internal/cli/parsers/base_argument_parsers.py +1 -0
- ansible_test/_internal/cli/parsers/helpers.py +1 -0
- ansible_test/_internal/cli/parsers/host_config_parsers.py +1 -0
- ansible_test/_internal/cli/parsers/key_value_parsers.py +1 -0
- ansible_test/_internal/cli/parsers/value_parsers.py +1 -0
- ansible_test/_internal/commands/__init__.py +1 -0
- ansible_test/_internal/commands/coverage/__init__.py +2 -1
- ansible_test/_internal/commands/coverage/analyze/__init__.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/__init__.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/combine.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/expand.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/filter.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/generate.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/missing.py +1 -0
- ansible_test/_internal/commands/coverage/combine.py +2 -1
- ansible_test/_internal/commands/coverage/erase.py +1 -0
- ansible_test/_internal/commands/coverage/html.py +1 -0
- ansible_test/_internal/commands/coverage/report.py +1 -0
- ansible_test/_internal/commands/coverage/xml.py +1 -0
- ansible_test/_internal/commands/env/__init__.py +2 -0
- ansible_test/_internal/commands/integration/__init__.py +4 -0
- ansible_test/_internal/commands/integration/cloud/__init__.py +1 -0
- ansible_test/_internal/commands/integration/cloud/acme.py +2 -1
- ansible_test/_internal/commands/integration/cloud/aws.py +1 -0
- ansible_test/_internal/commands/integration/cloud/azure.py +1 -0
- ansible_test/_internal/commands/integration/cloud/cs.py +1 -0
- ansible_test/_internal/commands/integration/cloud/digitalocean.py +1 -0
- ansible_test/_internal/commands/integration/cloud/galaxy.py +3 -2
- ansible_test/_internal/commands/integration/cloud/hcloud.py +1 -0
- ansible_test/_internal/commands/integration/cloud/httptester.py +2 -1
- ansible_test/_internal/commands/integration/cloud/nios.py +2 -1
- ansible_test/_internal/commands/integration/cloud/opennebula.py +1 -0
- ansible_test/_internal/commands/integration/cloud/openshift.py +1 -0
- ansible_test/_internal/commands/integration/cloud/scaleway.py +1 -0
- ansible_test/_internal/commands/integration/cloud/vcenter.py +1 -0
- ansible_test/_internal/commands/integration/cloud/vultr.py +1 -0
- ansible_test/_internal/commands/integration/coverage.py +1 -0
- ansible_test/_internal/commands/integration/filters.py +1 -0
- ansible_test/_internal/commands/integration/network.py +1 -0
- ansible_test/_internal/commands/integration/posix.py +1 -0
- ansible_test/_internal/commands/integration/windows.py +1 -0
- ansible_test/_internal/commands/sanity/__init__.py +16 -1
- ansible_test/_internal/commands/sanity/ansible_doc.py +1 -0
- ansible_test/_internal/commands/sanity/bin_symlinks.py +1 -0
- ansible_test/_internal/commands/sanity/compile.py +1 -0
- ansible_test/_internal/commands/sanity/ignores.py +1 -0
- ansible_test/_internal/commands/sanity/import.py +1 -0
- ansible_test/_internal/commands/sanity/integration_aliases.py +1 -0
- ansible_test/_internal/commands/sanity/pep8.py +1 -0
- ansible_test/_internal/commands/sanity/pslint.py +1 -0
- ansible_test/_internal/commands/sanity/pylint.py +24 -26
- ansible_test/_internal/commands/sanity/shellcheck.py +1 -0
- ansible_test/_internal/commands/sanity/validate_modules.py +1 -0
- ansible_test/_internal/commands/sanity/yamllint.py +1 -0
- ansible_test/_internal/commands/shell/__init__.py +1 -0
- ansible_test/_internal/commands/units/__init__.py +1 -0
- ansible_test/_internal/compat/__init__.py +1 -0
- ansible_test/_internal/compat/packaging.py +1 -0
- ansible_test/_internal/compat/yaml.py +1 -0
- ansible_test/_internal/completion.py +1 -0
- ansible_test/_internal/config.py +2 -0
- ansible_test/_internal/connections.py +1 -0
- ansible_test/_internal/constants.py +1 -0
- ansible_test/_internal/containers.py +1 -0
- ansible_test/_internal/content_config.py +1 -0
- ansible_test/_internal/core_ci.py +1 -0
- ansible_test/_internal/coverage_util.py +11 -10
- ansible_test/_internal/data.py +1 -0
- ansible_test/_internal/delegation.py +1 -0
- ansible_test/_internal/dev/__init__.py +1 -0
- ansible_test/_internal/dev/container_probe.py +1 -0
- ansible_test/_internal/diff.py +3 -2
- ansible_test/_internal/docker_util.py +2 -1
- ansible_test/_internal/encoding.py +1 -0
- ansible_test/_internal/executor.py +1 -0
- ansible_test/_internal/git.py +1 -0
- ansible_test/_internal/host_configs.py +1 -0
- ansible_test/_internal/host_profiles.py +1 -0
- ansible_test/_internal/http.py +1 -0
- ansible_test/_internal/init.py +1 -0
- ansible_test/_internal/inventory.py +35 -3
- ansible_test/_internal/io.py +1 -0
- ansible_test/_internal/metadata.py +1 -0
- ansible_test/_internal/payload.py +1 -0
- ansible_test/_internal/provider/__init__.py +1 -0
- ansible_test/_internal/provider/layout/__init__.py +1 -0
- ansible_test/_internal/provider/layout/ansible.py +1 -0
- ansible_test/_internal/provider/layout/collection.py +1 -0
- ansible_test/_internal/provider/layout/unsupported.py +1 -0
- ansible_test/_internal/provider/source/__init__.py +1 -0
- ansible_test/_internal/provider/source/git.py +1 -0
- ansible_test/_internal/provider/source/installed.py +1 -0
- ansible_test/_internal/provider/source/unsupported.py +1 -0
- ansible_test/_internal/provider/source/unversioned.py +1 -0
- ansible_test/_internal/provisioning.py +1 -0
- ansible_test/_internal/pypi_proxy.py +6 -5
- ansible_test/_internal/python_requirements.py +1 -0
- ansible_test/_internal/ssh.py +1 -0
- ansible_test/_internal/target.py +1 -0
- ansible_test/_internal/test.py +3 -2
- ansible_test/_internal/thread.py +1 -0
- ansible_test/_internal/timeout.py +1 -0
- ansible_test/_internal/util.py +1 -0
- ansible_test/_internal/util_common.py +5 -2
- ansible_test/_internal/venv.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/action-plugin-docs.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/changelog/sphinx.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/changelog.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/empty-init.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/line-endings.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-assert.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-get-exception.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-illegal-filenames.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-smart-quotes.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/replace-urlopen.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/runtime-metadata.py +28 -1
- ansible_test/_util/controller/sanity/code-smell/shebang.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/symlinks.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/use-argspec-type-path.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/use-compat-six.py +1 -0
- ansible_test/_util/controller/sanity/integration-aliases/yaml_to_json.py +2 -1
- ansible_test/_util/controller/sanity/pep8/current-ignore.txt +4 -0
- ansible_test/_util/controller/sanity/pylint/config/ansible-test-target.cfg +7 -5
- ansible_test/_util/controller/sanity/pylint/config/ansible-test.cfg +7 -5
- ansible_test/_util/controller/sanity/pylint/config/code-smell.cfg +7 -5
- ansible_test/_util/controller/sanity/pylint/config/collection.cfg +3 -5
- ansible_test/_util/controller/sanity/pylint/config/default.cfg +7 -7
- ansible_test/_util/controller/sanity/pylint/plugins/deprecated.py +1 -13
- ansible_test/_util/controller/sanity/pylint/plugins/hide_unraisable.py +1 -0
- ansible_test/_util/controller/sanity/pylint/plugins/string_format.py +1 -8
- ansible_test/_util/controller/sanity/pylint/plugins/unwanted.py +1 -8
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py +55 -28
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/module_args.py +12 -5
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/schema.py +13 -2
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/utils.py +1 -0
- ansible_test/_util/controller/sanity/yamllint/yamllinter.py +35 -17
- ansible_test/_util/controller/tools/collection_detail.py +1 -0
- ansible_test/_util/controller/tools/yaml_to_json.py +2 -1
- ansible_test/_util/target/pytest/plugins/ansible_forked.py +6 -1
- ansible_test/_util/target/pytest/plugins/ansible_pytest_collections.py +2 -1
- ansible_test/_util/target/pytest/plugins/ansible_pytest_coverage.py +1 -0
- ansible_test/_util/target/sanity/compile/compile.py +1 -0
- ansible_test/_util/target/sanity/import/importer.py +15 -16
- ansible_test/_util/target/setup/bootstrap.sh +9 -20
- ansible_test/_util/target/setup/probe_cgroups.py +1 -0
- ansible_test/_util/target/setup/quiet_pip.py +1 -0
- ansible_test/_util/target/setup/requirements.py +35 -27
- ansible_test/_util/target/tools/virtualenvcheck.py +2 -1
- ansible_test/_util/target/tools/yamlcheck.py +2 -1
- ansible/compat/selectors.py +0 -32
- ansible/errors/yaml_strings.py +0 -138
- ansible/executor/action_write_locks.py +0 -44
- ansible/executor/discovery/python_target.py +0 -47
- ansible/executor/powershell/module_powershell_wrapper.ps1 +0 -86
- ansible/executor/powershell/module_script_wrapper.ps1 +0 -22
- ansible/module_utils/compat/importlib.py +0 -26
- ansible/module_utils/compat/selectors.py +0 -32
- ansible/module_utils/pycompat24.py +0 -73
- ansible/parsing/utils/jsonify.py +0 -36
- ansible/parsing/yaml/constructor.py +0 -178
- ansible/template/native_helpers.py +0 -251
- ansible/template/template.py +0 -43
- ansible/template/vars.py +0 -77
- ansible/utils/native_jinja.py +0 -11
- ansible/vars/fact_cache.py +0 -71
- ansible_core-2.18.4rc1.dist-info/RECORD +0 -992
- {ansible_core-2.18.4rc1.dist-info → ansible_core-2.19.0b1.dist-info}/Apache-License.txt +0 -0
- {ansible_core-2.18.4rc1.dist-info → ansible_core-2.19.0b1.dist-info}/COPYING +0 -0
- {ansible_core-2.18.4rc1.dist-info → ansible_core-2.19.0b1.dist-info}/MIT-license.txt +0 -0
- {ansible_core-2.18.4rc1.dist-info → ansible_core-2.19.0b1.dist-info}/PSF-license.txt +0 -0
- {ansible_core-2.18.4rc1.dist-info → ansible_core-2.19.0b1.dist-info}/entry_points.txt +0 -0
- {ansible_core-2.18.4rc1.dist-info → ansible_core-2.19.0b1.dist-info}/simplified_bsd.txt +0 -0
- {ansible_core-2.18.4rc1.dist-info → ansible_core-2.19.0b1.dist-info}/top_level.txt +0 -0
@@ -17,24 +17,30 @@
|
|
17
17
|
|
18
18
|
from __future__ import annotations
|
19
19
|
|
20
|
+
import functools
|
20
21
|
import hashlib
|
21
22
|
import os
|
22
23
|
import string
|
24
|
+
import typing as t
|
23
25
|
|
24
26
|
from collections.abc import Mapping
|
25
27
|
|
26
|
-
from ansible
|
28
|
+
from ansible import template as _template
|
29
|
+
from ansible.errors import AnsibleError, AnsibleParserError, AnsibleValueOmittedError
|
27
30
|
from ansible.inventory.group import to_safe_group_name as original_safe
|
31
|
+
from ansible.module_utils._internal import _plugin_exec_context
|
28
32
|
from ansible.parsing.utils.addresses import parse_address
|
29
|
-
from ansible.
|
30
|
-
from ansible.plugins
|
33
|
+
from ansible.parsing.dataloader import DataLoader
|
34
|
+
from ansible.plugins import AnsiblePlugin, _ConfigurablePlugin
|
35
|
+
from ansible.plugins.cache import CachePluginAdjudicator
|
31
36
|
from ansible.module_utils.common.text.converters import to_bytes, to_native
|
32
|
-
from ansible.module_utils.parsing.convert_bool import boolean
|
33
37
|
from ansible.module_utils.six import string_types
|
34
|
-
from ansible.template import Templar
|
35
38
|
from ansible.utils.display import Display
|
36
39
|
from ansible.utils.vars import combine_vars, load_extra_vars
|
37
40
|
|
41
|
+
if t.TYPE_CHECKING:
|
42
|
+
from ansible.inventory.data import InventoryData
|
43
|
+
|
38
44
|
display = Display()
|
39
45
|
|
40
46
|
|
@@ -45,17 +51,17 @@ def to_safe_group_name(name):
|
|
45
51
|
|
46
52
|
|
47
53
|
def detect_range(line=None):
|
48
|
-
|
54
|
+
"""
|
49
55
|
A helper function that checks a given host line to see if it contains
|
50
56
|
a range pattern described in the docstring above.
|
51
57
|
|
52
58
|
Returns True if the given line contains a pattern, else False.
|
53
|
-
|
59
|
+
"""
|
54
60
|
return '[' in line
|
55
61
|
|
56
62
|
|
57
63
|
def expand_hostname_range(line=None):
|
58
|
-
|
64
|
+
"""
|
59
65
|
A helper function that expands a given line that contains a pattern
|
60
66
|
specified in top docstring, and returns a list that consists of the
|
61
67
|
expanded version.
|
@@ -65,7 +71,7 @@ def expand_hostname_range(line=None):
|
|
65
71
|
string splitting.
|
66
72
|
|
67
73
|
References: https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html#hosts-and-groups
|
68
|
-
|
74
|
+
"""
|
69
75
|
all_hosts = []
|
70
76
|
if line:
|
71
77
|
# A hostname such as db[1:6]-node is considered to consists
|
@@ -127,8 +133,11 @@ def expand_hostname_range(line=None):
|
|
127
133
|
|
128
134
|
|
129
135
|
def get_cache_plugin(plugin_name, **kwargs):
|
136
|
+
if not plugin_name:
|
137
|
+
raise AnsibleError("A cache plugin must be configured to use inventory caching.")
|
138
|
+
|
130
139
|
try:
|
131
|
-
cache =
|
140
|
+
cache = CachePluginAdjudicator(plugin_name, **kwargs)
|
132
141
|
except AnsibleError as e:
|
133
142
|
if 'fact_caching_connection' in to_native(e):
|
134
143
|
raise AnsibleError("error, '%s' inventory cache plugin requires the one of the following to be set "
|
@@ -136,17 +145,22 @@ def get_cache_plugin(plugin_name, **kwargs):
|
|
136
145
|
"[inventory]: cache_connection;\nEnvironment:\nANSIBLE_INVENTORY_CACHE_CONNECTION,\n"
|
137
146
|
"ANSIBLE_CACHE_PLUGIN_CONNECTION." % plugin_name)
|
138
147
|
else:
|
139
|
-
raise
|
148
|
+
raise
|
140
149
|
|
141
|
-
if
|
150
|
+
if cache._plugin.ansible_name != 'ansible.builtin.memory' and kwargs and not getattr(cache._plugin, '_options', None):
|
142
151
|
raise AnsibleError('Unable to use cache plugin {0} for inventory. Cache options were provided but may not reconcile '
|
143
152
|
'correctly unless set via set_options. Refer to the porting guide if the plugin derives user settings '
|
144
153
|
'from ansible.constants.'.format(plugin_name))
|
145
154
|
return cache
|
146
155
|
|
147
156
|
|
148
|
-
class
|
149
|
-
"""
|
157
|
+
class _BaseInventoryPlugin(AnsiblePlugin):
|
158
|
+
"""
|
159
|
+
Internal base implementation for inventory plugins.
|
160
|
+
|
161
|
+
Do not inherit from this directly, use one of its public subclasses instead.
|
162
|
+
Used to introduce an extra layer in the class hierarchy to allow Constructed to subclass this while remaining a mixin for existing inventory plugins.
|
163
|
+
"""
|
150
164
|
|
151
165
|
TYPE = 'generator'
|
152
166
|
|
@@ -156,17 +170,27 @@ class BaseInventoryPlugin(AnsiblePlugin):
|
|
156
170
|
# it by default.
|
157
171
|
_sanitize_group_name = staticmethod(to_safe_group_name)
|
158
172
|
|
159
|
-
def __init__(self):
|
173
|
+
def __init__(self) -> None:
|
160
174
|
|
161
|
-
super(
|
175
|
+
super().__init__()
|
162
176
|
|
163
177
|
self._options = {}
|
164
|
-
self.inventory = None
|
165
178
|
self.display = display
|
166
|
-
self._vars = {}
|
167
179
|
|
168
|
-
|
169
|
-
|
180
|
+
# These attributes are set by the parse() method on this (base) class.
|
181
|
+
self.loader: DataLoader | None = None
|
182
|
+
self.inventory: InventoryData | None = None
|
183
|
+
self._vars: dict[str, t.Any] | None = None
|
184
|
+
|
185
|
+
trusted_by_default: bool = False
|
186
|
+
"""Inventory plugins that only source templates from trusted sources can set this True to have trust automatically applied to all templates."""
|
187
|
+
|
188
|
+
@functools.cached_property
|
189
|
+
def templar(self) -> _template.Templar:
|
190
|
+
return _template.Templar(loader=self.loader)
|
191
|
+
|
192
|
+
def parse(self, inventory: InventoryData, loader: DataLoader, path: str, cache: bool = True) -> None:
|
193
|
+
""" Populates inventory from the given data. Raises an error on any parse failure
|
170
194
|
:arg inventory: a copy of the previously accumulated inventory data,
|
171
195
|
to be updated with any new data this plugin provides.
|
172
196
|
The inventory can be empty if no other source/plugin ran successfully.
|
@@ -177,20 +201,18 @@ class BaseInventoryPlugin(AnsiblePlugin):
|
|
177
201
|
but it can also be a raw string for this plugin to consume
|
178
202
|
:arg cache: a boolean that indicates if the plugin should use the cache or not
|
179
203
|
you can ignore if this plugin does not implement caching.
|
180
|
-
|
181
|
-
|
204
|
+
"""
|
182
205
|
self.loader = loader
|
183
206
|
self.inventory = inventory
|
184
|
-
self.templar = Templar(loader=loader)
|
185
207
|
self._vars = load_extra_vars(loader)
|
186
208
|
|
187
209
|
def verify_file(self, path):
|
188
|
-
|
210
|
+
""" Verify if file is usable by this plugin, base does minimal accessibility check
|
189
211
|
:arg path: a string that was passed as an inventory source,
|
190
212
|
it normally is a path to a config file, but this is not a requirement,
|
191
213
|
it can also be parsed itself as the inventory data to process.
|
192
214
|
So only call this base class if you expect it to be a file.
|
193
|
-
|
215
|
+
"""
|
194
216
|
|
195
217
|
valid = False
|
196
218
|
b_path = to_bytes(path, errors='surrogate_or_strict')
|
@@ -210,15 +232,14 @@ class BaseInventoryPlugin(AnsiblePlugin):
|
|
210
232
|
self.inventory.set_variable(host, k, variables[k])
|
211
233
|
|
212
234
|
def _read_config_data(self, path):
|
213
|
-
|
235
|
+
""" validate config and set options as appropriate
|
214
236
|
:arg path: path to common yaml format config file for this plugin
|
215
|
-
|
237
|
+
"""
|
216
238
|
|
217
|
-
config = {}
|
218
239
|
try:
|
219
240
|
# avoid loader cache so meta: refresh_inventory can pick up config changes
|
220
241
|
# if we read more than once, fs cache should be good enough
|
221
|
-
config = self.loader.load_from_file(path, cache='none')
|
242
|
+
config = self.loader.load_from_file(path, cache='none', trusted_as_template=True)
|
222
243
|
except Exception as e:
|
223
244
|
raise AnsibleParserError(to_native(e))
|
224
245
|
|
@@ -244,20 +265,20 @@ class BaseInventoryPlugin(AnsiblePlugin):
|
|
244
265
|
return config
|
245
266
|
|
246
267
|
def _consume_options(self, data):
|
247
|
-
|
268
|
+
""" update existing options from alternate configuration sources not normally used by Ansible.
|
248
269
|
Many API libraries already have existing configuration sources, this allows plugin author to leverage them.
|
249
270
|
:arg data: key/value pairs that correspond to configuration options for this plugin
|
250
|
-
|
271
|
+
"""
|
251
272
|
|
252
273
|
for k in self._options:
|
253
274
|
if k in data:
|
254
275
|
self._options[k] = data.pop(k)
|
255
276
|
|
256
277
|
def _expand_hostpattern(self, hostpattern):
|
257
|
-
|
278
|
+
"""
|
258
279
|
Takes a single host pattern and returns a list of hostnames and an
|
259
280
|
optional port number that applies to all of them.
|
260
|
-
|
281
|
+
"""
|
261
282
|
# Can the given hostpattern be parsed as a host with an optional port
|
262
283
|
# specification?
|
263
284
|
|
@@ -279,7 +300,11 @@ class BaseInventoryPlugin(AnsiblePlugin):
|
|
279
300
|
return (hostnames, port)
|
280
301
|
|
281
302
|
|
282
|
-
class
|
303
|
+
class BaseInventoryPlugin(_BaseInventoryPlugin):
|
304
|
+
""" Parses an Inventory Source """
|
305
|
+
|
306
|
+
|
307
|
+
class BaseFileInventoryPlugin(_BaseInventoryPlugin):
|
283
308
|
""" Parses a File based Inventory Source"""
|
284
309
|
|
285
310
|
TYPE = 'storage'
|
@@ -289,51 +314,44 @@ class BaseFileInventoryPlugin(BaseInventoryPlugin):
|
|
289
314
|
super(BaseFileInventoryPlugin, self).__init__()
|
290
315
|
|
291
316
|
|
292
|
-
class Cacheable(
|
317
|
+
class Cacheable(_plugin_exec_context.HasPluginInfo, _ConfigurablePlugin):
|
318
|
+
"""Mixin for inventory plugins which support caching."""
|
293
319
|
|
294
|
-
_cache
|
320
|
+
_cache: CachePluginAdjudicator
|
295
321
|
|
296
322
|
@property
|
297
|
-
def cache(self):
|
323
|
+
def cache(self) -> CachePluginAdjudicator:
|
298
324
|
return self._cache
|
299
325
|
|
300
|
-
def load_cache_plugin(self):
|
326
|
+
def load_cache_plugin(self) -> None:
|
301
327
|
plugin_name = self.get_option('cache_plugin')
|
302
328
|
cache_option_keys = [('_uri', 'cache_connection'), ('_timeout', 'cache_timeout'), ('_prefix', 'cache_prefix')]
|
303
329
|
cache_options = dict((opt[0], self.get_option(opt[1])) for opt in cache_option_keys if self.get_option(opt[1]) is not None)
|
304
330
|
self._cache = get_cache_plugin(plugin_name, **cache_options)
|
305
331
|
|
306
|
-
def get_cache_key(self, path):
|
307
|
-
return
|
308
|
-
|
309
|
-
def _get_cache_prefix(self, path):
|
310
|
-
''' create predictable unique prefix for plugin/inventory '''
|
311
|
-
|
312
|
-
m = hashlib.sha1()
|
313
|
-
m.update(to_bytes(self.NAME, errors='surrogate_or_strict'))
|
314
|
-
d1 = m.hexdigest()
|
315
|
-
|
316
|
-
n = hashlib.sha1()
|
317
|
-
n.update(to_bytes(path, errors='surrogate_or_strict'))
|
318
|
-
d2 = n.hexdigest()
|
332
|
+
def get_cache_key(self, path: str) -> str:
|
333
|
+
return f'{self.ansible_name}_{self._get_cache_prefix(path)}'
|
319
334
|
|
320
|
-
|
335
|
+
def _get_cache_prefix(self, path: str) -> str:
|
336
|
+
"""Return a predictable unique key based on the given path."""
|
337
|
+
# DTFIX-RELEASE: choose a better hashing approach
|
338
|
+
return 'k' + hashlib.sha256(f'{self.ansible_name}{path}'.encode(), usedforsecurity=False).hexdigest()[:6]
|
321
339
|
|
322
|
-
def clear_cache(self):
|
323
|
-
self._cache.
|
340
|
+
def clear_cache(self) -> None:
|
341
|
+
self._cache.clear()
|
324
342
|
|
325
|
-
def update_cache_if_changed(self):
|
343
|
+
def update_cache_if_changed(self) -> None:
|
326
344
|
self._cache.update_cache_if_changed()
|
327
345
|
|
328
|
-
def set_cache_plugin(self):
|
346
|
+
def set_cache_plugin(self) -> None:
|
329
347
|
self._cache.set_cache()
|
330
348
|
|
331
349
|
|
332
|
-
class Constructable(
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
350
|
+
class Constructable(_BaseInventoryPlugin):
|
351
|
+
def _compose(self, template, variables, disable_lookups=...):
|
352
|
+
""" helper method for plugins to compose variables for Ansible based on jinja2 expression and inventory vars"""
|
353
|
+
if disable_lookups is not ...:
|
354
|
+
self.display.deprecated("The disable_lookups arg has no effect.", version="2.23")
|
337
355
|
|
338
356
|
try:
|
339
357
|
use_extra = self.get_option('use_extra_vars')
|
@@ -341,15 +359,14 @@ class Constructable(object):
|
|
341
359
|
use_extra = False
|
342
360
|
|
343
361
|
if use_extra:
|
344
|
-
|
362
|
+
self.templar.available_variables = combine_vars(variables, self._vars)
|
345
363
|
else:
|
346
|
-
|
364
|
+
self.templar.available_variables = variables
|
347
365
|
|
348
|
-
return
|
349
|
-
disable_lookups=disable_lookups)
|
366
|
+
return self.templar.evaluate_expression(template)
|
350
367
|
|
351
368
|
def _set_composite_vars(self, compose, variables, host, strict=False):
|
352
|
-
|
369
|
+
""" loops over compose entries to create vars for hosts """
|
353
370
|
if compose and isinstance(compose, dict):
|
354
371
|
for varname in compose:
|
355
372
|
try:
|
@@ -361,17 +378,17 @@ class Constructable(object):
|
|
361
378
|
self.inventory.set_variable(host, varname, composite)
|
362
379
|
|
363
380
|
def _add_host_to_composed_groups(self, groups, variables, host, strict=False, fetch_hostvars=True):
|
364
|
-
|
381
|
+
""" helper to create complex groups for plugins based on jinja2 conditionals, hosts that meet the conditional are added to group"""
|
365
382
|
# process each 'group entry'
|
366
383
|
if groups and isinstance(groups, dict):
|
367
384
|
if fetch_hostvars:
|
368
385
|
variables = combine_vars(variables, self.inventory.get_host(host).get_vars())
|
369
386
|
self.templar.available_variables = variables
|
370
387
|
for group_name in groups:
|
371
|
-
conditional =
|
388
|
+
conditional = groups[group_name]
|
372
389
|
group_name = self._sanitize_group_name(group_name)
|
373
390
|
try:
|
374
|
-
result =
|
391
|
+
result = self.templar.evaluate_conditional(conditional)
|
375
392
|
except Exception as e:
|
376
393
|
if strict:
|
377
394
|
raise AnsibleParserError("Could not add host %s to group %s: %s" % (host, group_name, to_native(e)))
|
@@ -384,7 +401,7 @@ class Constructable(object):
|
|
384
401
|
self.inventory.add_child(group_name, host)
|
385
402
|
|
386
403
|
def _add_host_to_keyed_groups(self, keys, variables, host, strict=False, fetch_hostvars=True):
|
387
|
-
|
404
|
+
""" helper to create groups for plugins based on variable values and add the corresponding hosts to it"""
|
388
405
|
if keys and isinstance(keys, list):
|
389
406
|
for keyed in keys:
|
390
407
|
if keyed and isinstance(keyed, dict):
|
@@ -405,13 +422,16 @@ class Constructable(object):
|
|
405
422
|
prefix = keyed.get('prefix', '')
|
406
423
|
sep = keyed.get('separator', '_')
|
407
424
|
raw_parent_name = keyed.get('parent_group', None)
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
425
|
+
|
426
|
+
try:
|
427
|
+
raw_parent_name = self.templar.template(raw_parent_name)
|
428
|
+
except AnsibleValueOmittedError:
|
429
|
+
raw_parent_name = None
|
430
|
+
except Exception as ex:
|
431
|
+
if strict:
|
432
|
+
raise AnsibleParserError(f'Could not generate parent group {raw_parent_name!r} for group {key!r}: {ex}') from ex
|
433
|
+
|
434
|
+
continue
|
415
435
|
|
416
436
|
new_raw_group_names = []
|
417
437
|
if isinstance(key, string_types):
|
@@ -3,22 +3,22 @@
|
|
3
3
|
|
4
4
|
from __future__ import annotations
|
5
5
|
|
6
|
-
DOCUMENTATION =
|
6
|
+
DOCUMENTATION = """
|
7
7
|
name: advanced_host_list
|
8
8
|
version_added: "2.4"
|
9
9
|
short_description: Parses a 'host list' with ranges
|
10
10
|
description:
|
11
11
|
- Parses a host list string as a comma separated values of hosts and supports host ranges.
|
12
12
|
- This plugin only applies to inventory sources that are not paths and contain at least one comma.
|
13
|
-
|
13
|
+
"""
|
14
14
|
|
15
|
-
EXAMPLES =
|
15
|
+
EXAMPLES = """
|
16
16
|
# simple range
|
17
17
|
# ansible -i 'host[1:10],' -m ping
|
18
18
|
|
19
19
|
# still supports w/o ranges also
|
20
20
|
# ansible-playbook -i 'localhost,' play.yml
|
21
|
-
|
21
|
+
"""
|
22
22
|
|
23
23
|
import os
|
24
24
|
|
@@ -31,6 +31,8 @@ class InventoryModule(BaseInventoryPlugin):
|
|
31
31
|
|
32
32
|
NAME = 'advanced_host_list'
|
33
33
|
|
34
|
+
# advanced_host_list does not set vars, so needs no special trust assistance from the inventory API
|
35
|
+
|
34
36
|
def verify_file(self, host_list):
|
35
37
|
|
36
38
|
valid = False
|
@@ -40,7 +42,7 @@ class InventoryModule(BaseInventoryPlugin):
|
|
40
42
|
return valid
|
41
43
|
|
42
44
|
def parse(self, inventory, loader, host_list, cache=True):
|
43
|
-
|
45
|
+
""" parses the inventory file """
|
44
46
|
|
45
47
|
super(InventoryModule, self).parse(inventory, loader, host_list)
|
46
48
|
|
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
from __future__ import annotations
|
5
5
|
|
6
|
-
DOCUMENTATION =
|
6
|
+
DOCUMENTATION = """
|
7
7
|
name: auto
|
8
8
|
author:
|
9
9
|
- Matt Davis (@nitzmahone)
|
@@ -14,12 +14,12 @@ DOCUMENTATION = '''
|
|
14
14
|
C(plugin) key at its root will automatically cause the named plugin to be loaded and executed with that
|
15
15
|
config. This effectively provides automatic enabling of all installed/accessible inventory plugins.
|
16
16
|
- To disable this behavior, remove C(auto) from the C(INVENTORY_ENABLED) config element.
|
17
|
-
|
17
|
+
"""
|
18
18
|
|
19
|
-
EXAMPLES =
|
19
|
+
EXAMPLES = """
|
20
20
|
# This plugin is not intended for direct use; it is a fallback mechanism for automatic enabling of
|
21
21
|
# all installed inventory plugins.
|
22
|
-
|
22
|
+
"""
|
23
23
|
|
24
24
|
from ansible.errors import AnsibleParserError
|
25
25
|
from ansible.plugins.inventory import BaseInventoryPlugin
|
@@ -30,6 +30,8 @@ class InventoryModule(BaseInventoryPlugin):
|
|
30
30
|
|
31
31
|
NAME = 'auto'
|
32
32
|
|
33
|
+
# no need to set trusted_by_default, since the consumers of this value will always consult the real plugin substituted during our parse()
|
34
|
+
|
33
35
|
def verify_file(self, path):
|
34
36
|
if not path.endswith('.yml') and not path.endswith('.yaml'):
|
35
37
|
return False
|
@@ -55,6 +57,11 @@ class InventoryModule(BaseInventoryPlugin):
|
|
55
57
|
raise AnsibleParserError("inventory source '{0}' could not be verified by inventory plugin '{1}'".format(path, plugin_name))
|
56
58
|
|
57
59
|
self.display.v("Using inventory plugin '{0}' to process inventory source '{1}'".format(plugin._load_name, path))
|
60
|
+
|
61
|
+
# unfortunate magic to swap the real plugin type we're proxying here into the inventory data API wrapper, so the wrapper can make the right compat
|
62
|
+
# decisions based on the metadata the real plugin provides instead of our metadata
|
63
|
+
inventory._target_plugin = plugin
|
64
|
+
|
58
65
|
plugin.parse(inventory, loader, path, cache=cache)
|
59
66
|
try:
|
60
67
|
plugin.update_cache_if_changed()
|
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
from __future__ import annotations
|
5
5
|
|
6
|
-
DOCUMENTATION =
|
6
|
+
DOCUMENTATION = """
|
7
7
|
name: constructed
|
8
8
|
version_added: "2.4"
|
9
9
|
short_description: Uses Jinja2 to construct vars and groups based on existing inventory.
|
@@ -33,9 +33,9 @@ DOCUMENTATION = '''
|
|
33
33
|
version_added: '2.11'
|
34
34
|
extends_documentation_fragment:
|
35
35
|
- constructed
|
36
|
-
|
36
|
+
"""
|
37
37
|
|
38
|
-
EXAMPLES = r
|
38
|
+
EXAMPLES = r"""
|
39
39
|
# inventory.config file in YAML format
|
40
40
|
plugin: ansible.builtin.constructed
|
41
41
|
strict: False
|
@@ -77,17 +77,16 @@ EXAMPLES = r'''
|
|
77
77
|
# this creates a common parent group for all ec2 availability zones
|
78
78
|
- key: placement.availability_zone
|
79
79
|
parent_group: all_ec2_zones
|
80
|
-
|
80
|
+
"""
|
81
81
|
|
82
82
|
import os
|
83
83
|
|
84
84
|
from ansible import constants as C
|
85
|
-
from ansible.errors import AnsibleParserError
|
85
|
+
from ansible.errors import AnsibleParserError
|
86
86
|
from ansible.inventory.helpers import get_group_vars
|
87
87
|
from ansible.plugins.inventory import BaseInventoryPlugin, Constructable
|
88
|
-
from ansible.
|
88
|
+
from ansible.plugins.loader import cache_loader
|
89
89
|
from ansible.utils.vars import combine_vars
|
90
|
-
from ansible.vars.fact_cache import FactCache
|
91
90
|
from ansible.vars.plugins import get_vars_from_inventory_sources
|
92
91
|
|
93
92
|
|
@@ -96,11 +95,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
|
|
96
95
|
|
97
96
|
NAME = 'constructed'
|
98
97
|
|
99
|
-
|
100
|
-
|
101
|
-
super(InventoryModule, self).__init__()
|
102
|
-
|
103
|
-
self._cache = FactCache()
|
98
|
+
# implicit trust behavior is already added by the YAML parser invoked by the loader
|
104
99
|
|
105
100
|
def verify_file(self, path):
|
106
101
|
|
@@ -114,11 +109,11 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
|
|
114
109
|
return valid
|
115
110
|
|
116
111
|
def get_all_host_vars(self, host, loader, sources):
|
117
|
-
|
112
|
+
""" requires host object """
|
118
113
|
return combine_vars(self.host_groupvars(host, loader, sources), self.host_vars(host, loader, sources))
|
119
114
|
|
120
115
|
def host_groupvars(self, host, loader, sources):
|
121
|
-
|
116
|
+
""" requires host object """
|
122
117
|
gvars = get_group_vars(host.get_groups())
|
123
118
|
|
124
119
|
if self.get_option('use_vars_plugins'):
|
@@ -127,7 +122,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
|
|
127
122
|
return gvars
|
128
123
|
|
129
124
|
def host_vars(self, host, loader, sources):
|
130
|
-
|
125
|
+
""" requires host object """
|
131
126
|
hvars = host.get_vars()
|
132
127
|
|
133
128
|
if self.get_option('use_vars_plugins'):
|
@@ -136,7 +131,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
|
|
136
131
|
return hvars
|
137
132
|
|
138
133
|
def parse(self, inventory, loader, path, cache=False):
|
139
|
-
|
134
|
+
""" parses the inventory file """
|
140
135
|
|
141
136
|
super(InventoryModule, self).parse(inventory, loader, path, cache=cache)
|
142
137
|
|
@@ -147,26 +142,28 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
|
|
147
142
|
sources = inventory.processed_sources
|
148
143
|
except AttributeError:
|
149
144
|
if self.get_option('use_vars_plugins'):
|
150
|
-
raise
|
145
|
+
raise
|
151
146
|
|
152
147
|
strict = self.get_option('strict')
|
153
|
-
|
148
|
+
|
149
|
+
cache = cache_loader.get(C.CACHE_PLUGIN)
|
150
|
+
|
154
151
|
try:
|
155
152
|
# Go over hosts (less var copies)
|
156
153
|
for host in inventory.hosts:
|
157
154
|
|
158
155
|
# get available variables to templar
|
159
156
|
hostvars = self.get_all_host_vars(inventory.hosts[host], loader, sources)
|
160
|
-
if host
|
161
|
-
hostvars = combine_vars(hostvars,
|
157
|
+
if cache.contains(host): # adds facts if cache is active
|
158
|
+
hostvars = combine_vars(hostvars, cache.get(host))
|
162
159
|
|
163
160
|
# create composite vars
|
164
161
|
self._set_composite_vars(self.get_option('compose'), hostvars, host, strict=strict)
|
165
162
|
|
166
163
|
# refetch host vars in case new ones have been created above
|
167
164
|
hostvars = self.get_all_host_vars(inventory.hosts[host], loader, sources)
|
168
|
-
if host
|
169
|
-
hostvars = combine_vars(hostvars,
|
165
|
+
if cache.contains(host): # adds facts if cache is active
|
166
|
+
hostvars = combine_vars(hostvars, cache.get(host))
|
170
167
|
|
171
168
|
# constructed groups based on conditionals
|
172
169
|
self._add_host_to_composed_groups(self.get_option('groups'), hostvars, host, strict=strict, fetch_hostvars=False)
|
@@ -174,5 +171,5 @@ class InventoryModule(BaseInventoryPlugin, Constructable):
|
|
174
171
|
# constructed groups based variable values
|
175
172
|
self._add_host_to_keyed_groups(self.get_option('keyed_groups'), hostvars, host, strict=strict, fetch_hostvars=False)
|
176
173
|
|
177
|
-
except Exception as
|
178
|
-
raise AnsibleParserError("
|
174
|
+
except Exception as ex:
|
175
|
+
raise AnsibleParserError(f"Failed to parse {path!r}.") from ex
|
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
from __future__ import annotations
|
5
5
|
|
6
|
-
DOCUMENTATION =
|
6
|
+
DOCUMENTATION = """
|
7
7
|
name: generator
|
8
8
|
version_added: "2.6"
|
9
9
|
short_description: Uses Jinja2 to construct hosts and groups from patterns
|
@@ -32,9 +32,9 @@ DOCUMENTATION = '''
|
|
32
32
|
description:
|
33
33
|
- A dictionary of layers, with the key being the layer name, used as a variable name in the C(host)
|
34
34
|
C(name) and C(parents) keys. Each layer value is a list of possible values for that layer.
|
35
|
-
|
35
|
+
"""
|
36
36
|
|
37
|
-
EXAMPLES =
|
37
|
+
EXAMPLES = """
|
38
38
|
# inventory.config file in YAML format
|
39
39
|
# remember to enable this inventory plugin in the ansible.cfg before using
|
40
40
|
# View the output using `ansible-inventory -i inventory.config --list`
|
@@ -68,7 +68,7 @@ EXAMPLES = '''
|
|
68
68
|
application:
|
69
69
|
- web
|
70
70
|
- api
|
71
|
-
|
71
|
+
"""
|
72
72
|
|
73
73
|
import os
|
74
74
|
|
@@ -84,6 +84,8 @@ class InventoryModule(BaseInventoryPlugin):
|
|
84
84
|
|
85
85
|
NAME = 'generator'
|
86
86
|
|
87
|
+
# implicit trust behavior is already added by the YAML parser invoked by the loader
|
88
|
+
|
87
89
|
def __init__(self):
|
88
90
|
|
89
91
|
super(InventoryModule, self).__init__()
|
@@ -100,15 +102,18 @@ class InventoryModule(BaseInventoryPlugin):
|
|
100
102
|
return valid
|
101
103
|
|
102
104
|
def template(self, pattern, variables):
|
103
|
-
|
104
|
-
|
105
|
+
# Allow pass-through of data structures for templating later (if applicable).
|
106
|
+
# This limitation was part of the original plugin implementation and was updated to maintain feature parity with the new templating API.
|
107
|
+
if not isinstance(pattern, str):
|
108
|
+
return pattern
|
109
|
+
|
110
|
+
return self.templar.copy_with_new_env(available_variables=variables).template(pattern)
|
105
111
|
|
106
112
|
def add_parents(self, inventory, child, parents, template_vars):
|
107
113
|
for parent in parents:
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
raise AnsibleParserError("Element %s has a parent with no name element" % child['name'])
|
114
|
+
groupname = self.template(parent.get('name'), template_vars)
|
115
|
+
if not groupname:
|
116
|
+
raise AnsibleParserError(f"Element {child} has a parent with no name.")
|
112
117
|
if groupname not in inventory.groups:
|
113
118
|
inventory.add_group(groupname)
|
114
119
|
group = inventory.groups[groupname]
|
@@ -118,7 +123,7 @@ class InventoryModule(BaseInventoryPlugin):
|
|
118
123
|
self.add_parents(inventory, groupname, parent.get('parents', []), template_vars)
|
119
124
|
|
120
125
|
def parse(self, inventory, loader, path, cache=False):
|
121
|
-
|
126
|
+
""" parses the inventory file """
|
122
127
|
|
123
128
|
super(InventoryModule, self).parse(inventory, loader, path, cache=cache)
|
124
129
|
|