ansible-core 2.18.7rc1__py3-none-any.whl → 2.19.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ansible-core might be problematic. Click here for more details.
- ansible/_internal/__init__.py +53 -0
- ansible/_internal/_ansiballz/__init__.py +0 -0
- ansible/_internal/_ansiballz/_builder.py +101 -0
- ansible/_internal/_ansiballz/_wrapper.py +262 -0
- ansible/_internal/_collection_proxy.py +47 -0
- ansible/_internal/_datatag/__init__.py +0 -0
- ansible/_internal/_datatag/_tags.py +130 -0
- ansible/_internal/_datatag/_utils.py +19 -0
- ansible/_internal/_datatag/_wrappers.py +33 -0
- ansible/_internal/_errors/__init__.py +0 -0
- ansible/_internal/_errors/_alarm_timeout.py +66 -0
- ansible/_internal/_errors/_captured.py +123 -0
- ansible/_internal/_errors/_error_factory.py +89 -0
- ansible/_internal/_errors/_error_utils.py +240 -0
- ansible/_internal/_errors/_handler.py +91 -0
- ansible/_internal/_errors/_task_timeout.py +28 -0
- ansible/_internal/_event_formatting.py +127 -0
- ansible/_internal/_json/__init__.py +214 -0
- ansible/_internal/_json/_legacy_encoder.py +34 -0
- ansible/_internal/_json/_profiles/__init__.py +0 -0
- ansible/_internal/_json/_profiles/_cache_persistence.py +57 -0
- ansible/_internal/_json/_profiles/_inventory_legacy.py +40 -0
- ansible/_internal/_json/_profiles/_legacy.py +189 -0
- ansible/_internal/_locking.py +21 -0
- ansible/_internal/_plugins/__init__.py +0 -0
- ansible/_internal/_plugins/_cache.py +57 -0
- ansible/_internal/_ssh/__init__.py +0 -0
- ansible/_internal/_ssh/_agent_launch.py +91 -0
- ansible/_internal/_ssh/_ssh_agent.py +619 -0
- ansible/_internal/_task.py +78 -0
- ansible/_internal/_templating/__init__.py +12 -0
- ansible/_internal/_templating/_access.py +86 -0
- ansible/_internal/_templating/_chain_templar.py +63 -0
- ansible/_internal/_templating/_datatag.py +95 -0
- ansible/_internal/_templating/_engine.py +592 -0
- ansible/_internal/_templating/_errors.py +28 -0
- ansible/_internal/_templating/_jinja_bits.py +1106 -0
- ansible/_internal/_templating/_jinja_common.py +323 -0
- ansible/_internal/_templating/_jinja_patches.py +44 -0
- ansible/_internal/_templating/_jinja_plugins.py +375 -0
- ansible/_internal/_templating/_lazy_containers.py +633 -0
- ansible/_internal/_templating/_marker_behaviors.py +103 -0
- ansible/_internal/_templating/_template_vars.py +72 -0
- ansible/_internal/_templating/_transform.py +70 -0
- ansible/_internal/_templating/_utils.py +108 -0
- ansible/_internal/_testing.py +26 -0
- ansible/_internal/_wrapt.py +1052 -0
- ansible/_internal/_yaml/__init__.py +0 -0
- ansible/_internal/_yaml/_constructor.py +240 -0
- ansible/_internal/_yaml/_dumper.py +70 -0
- ansible/_internal/_yaml/_errors.py +166 -0
- ansible/_internal/_yaml/_loader.py +66 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/README.md +11 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/action/debug.py +36 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/apply_trust.py +19 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/dump_object.py +27 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/finalize.py +16 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/origin.py +18 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/python_literal_eval.py +24 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/python_literal_eval.yml +33 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/tag_names.py +16 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/true_type.py +17 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/unmask.py +49 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/lookup/config.py +21 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/lookup/config.yml +2 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged.py +15 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged.yml +19 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged_with.py +18 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged_with.yml +19 -0
- ansible/cli/__init__.py +93 -104
- ansible/cli/_ssh_askpass.py +54 -0
- ansible/cli/adhoc.py +20 -10
- ansible/cli/arguments/option_helpers.py +163 -10
- ansible/cli/config.py +43 -68
- ansible/cli/console.py +13 -11
- ansible/cli/doc.py +134 -77
- ansible/cli/galaxy.py +27 -20
- ansible/cli/inventory.py +28 -28
- ansible/cli/playbook.py +4 -12
- ansible/cli/pull.py +6 -3
- ansible/cli/scripts/ansible_connection_cli_stub.py +7 -7
- ansible/cli/vault.py +12 -11
- ansible/compat/__init__.py +2 -2
- ansible/compat/importlib_resources.py +9 -12
- ansible/config/base.yml +218 -133
- ansible/config/manager.py +220 -159
- ansible/constants.py +2 -65
- ansible/errors/__init__.py +350 -256
- ansible/executor/interpreter_discovery.py +28 -149
- ansible/executor/module_common.py +480 -514
- ansible/executor/play_iterator.py +22 -27
- ansible/executor/playbook_executor.py +11 -11
- ansible/executor/powershell/async_watchdog.ps1 +97 -102
- ansible/executor/powershell/async_wrapper.ps1 +204 -153
- ansible/executor/powershell/become_wrapper.ps1 +107 -144
- ansible/executor/powershell/bootstrap_wrapper.ps1 +46 -9
- ansible/executor/powershell/coverage_wrapper.ps1 +91 -135
- ansible/executor/powershell/exec_wrapper.ps1 +675 -196
- ansible/executor/powershell/module_manifest.py +469 -265
- ansible/executor/powershell/module_wrapper.ps1 +195 -186
- ansible/executor/powershell/powershell_expand_user.ps1 +20 -0
- ansible/executor/powershell/powershell_mkdtemp.ps1 +17 -0
- ansible/executor/powershell/psrp_fetch_file.ps1 +41 -0
- ansible/executor/powershell/psrp_put_file.ps1 +122 -0
- ansible/executor/powershell/winrm_fetch_file.ps1 +46 -0
- ansible/executor/powershell/winrm_put_file.ps1 +36 -0
- ansible/executor/process/worker.py +139 -149
- ansible/executor/stats.py +5 -5
- ansible/executor/task_executor.py +270 -297
- ansible/executor/task_queue_manager.py +135 -137
- ansible/executor/task_result.py +182 -79
- ansible/galaxy/__init__.py +2 -2
- ansible/galaxy/api.py +26 -25
- ansible/galaxy/collection/__init__.py +6 -14
- ansible/galaxy/collection/concrete_artifact_manager.py +12 -21
- ansible/galaxy/dependency_resolution/dataclasses.py +14 -4
- ansible/galaxy/dependency_resolution/providers.py +4 -4
- ansible/galaxy/dependency_resolution/reporters.py +81 -0
- ansible/galaxy/role.py +6 -10
- ansible/galaxy/token.py +28 -21
- ansible/inventory/data.py +47 -57
- ansible/inventory/group.py +50 -73
- ansible/inventory/helpers.py +9 -0
- ansible/inventory/host.py +37 -54
- ansible/inventory/manager.py +79 -34
- ansible/keyword_desc.yml +1 -1
- ansible/module_utils/_internal/__init__.py +55 -0
- ansible/module_utils/_internal/_ambient_context.py +58 -0
- ansible/module_utils/_internal/_ansiballz/__init__.py +0 -0
- ansible/module_utils/_internal/_ansiballz/_extensions/__init__.py +0 -0
- ansible/module_utils/_internal/_ansiballz/_extensions/_coverage.py +45 -0
- ansible/module_utils/_internal/_ansiballz/_extensions/_pydevd.py +62 -0
- ansible/module_utils/_internal/_ansiballz/_loader.py +81 -0
- ansible/module_utils/_internal/_ansiballz/_respawn.py +32 -0
- ansible/module_utils/_internal/_ansiballz/_respawn_wrapper.py +23 -0
- ansible/module_utils/_internal/_concurrent/_daemon_threading.py +1 -0
- ansible/module_utils/_internal/_dataclass_validation.py +217 -0
- ansible/module_utils/_internal/_datatag/__init__.py +961 -0
- ansible/module_utils/_internal/_datatag/_tags.py +16 -0
- ansible/module_utils/_internal/_debugging.py +31 -0
- ansible/module_utils/_internal/_deprecator.py +157 -0
- ansible/module_utils/_internal/_errors.py +101 -0
- ansible/module_utils/_internal/_event_utils.py +61 -0
- ansible/module_utils/_internal/_json/__init__.py +63 -0
- ansible/module_utils/_internal/_json/_legacy_encoder.py +26 -0
- ansible/module_utils/_internal/_json/_profiles/__init__.py +428 -0
- ansible/module_utils/_internal/_json/_profiles/_fallback_to_str.py +73 -0
- ansible/module_utils/_internal/_json/_profiles/_module_legacy_c2m.py +33 -0
- ansible/module_utils/_internal/_json/_profiles/_module_legacy_m2c.py +37 -0
- ansible/module_utils/_internal/_json/_profiles/_module_modern_c2m.py +35 -0
- ansible/module_utils/_internal/_json/_profiles/_module_modern_m2c.py +33 -0
- ansible/module_utils/_internal/_json/_profiles/_tagless.py +52 -0
- ansible/module_utils/_internal/_messages.py +130 -0
- ansible/module_utils/_internal/_patches/__init__.py +66 -0
- ansible/module_utils/_internal/_patches/_dataclass_annotation_patch.py +53 -0
- ansible/module_utils/_internal/_patches/_socket_patch.py +34 -0
- ansible/module_utils/_internal/_patches/_sys_intern_patch.py +34 -0
- ansible/module_utils/_internal/_plugin_info.py +38 -0
- ansible/module_utils/_internal/_stack.py +22 -0
- ansible/module_utils/_internal/_testing.py +0 -0
- ansible/module_utils/_internal/_text_utils.py +6 -0
- ansible/module_utils/_internal/_traceback.py +92 -0
- ansible/module_utils/_internal/_validation.py +14 -0
- ansible/module_utils/ansible_release.py +2 -2
- ansible/module_utils/api.py +1 -2
- ansible/module_utils/basic.py +303 -202
- ansible/module_utils/common/_utils.py +24 -28
- ansible/module_utils/common/arg_spec.py +8 -3
- ansible/module_utils/common/collections.py +7 -2
- ansible/module_utils/common/dict_transformations.py +2 -2
- ansible/module_utils/common/file.py +2 -2
- ansible/module_utils/common/json.py +90 -84
- ansible/module_utils/common/locale.py +2 -2
- ansible/module_utils/common/parameters.py +27 -24
- ansible/module_utils/common/process.py +2 -3
- ansible/module_utils/common/respawn.py +11 -33
- ansible/module_utils/common/sentinel.py +66 -0
- ansible/module_utils/common/sys_info.py +8 -8
- ansible/module_utils/common/text/converters.py +16 -37
- ansible/module_utils/common/validation.py +35 -24
- ansible/module_utils/common/warnings.py +143 -25
- ansible/module_utils/common/yaml.py +29 -3
- ansible/module_utils/compat/datetime.py +33 -21
- ansible/module_utils/compat/paramiko.py +21 -10
- ansible/module_utils/compat/typing.py +6 -5
- ansible/module_utils/connection.py +10 -13
- ansible/module_utils/csharp/Ansible.Basic.cs +15 -12
- ansible/module_utils/csharp/Ansible.Become.cs +1 -0
- ansible/module_utils/csharp/Ansible.Privilege.cs +2 -2
- ansible/module_utils/csharp/Ansible._Async.cs +517 -0
- ansible/module_utils/datatag.py +49 -0
- ansible/module_utils/distro/__init__.py +2 -2
- ansible/module_utils/facts/ansible_collector.py +4 -5
- ansible/module_utils/facts/collector.py +13 -14
- ansible/module_utils/facts/compat.py +4 -4
- ansible/module_utils/facts/default_collectors.py +1 -1
- ansible/module_utils/facts/hardware/aix.py +34 -0
- ansible/module_utils/facts/hardware/base.py +2 -2
- ansible/module_utils/facts/hardware/darwin.py +1 -3
- ansible/module_utils/facts/hardware/freebsd.py +2 -2
- ansible/module_utils/facts/hardware/linux.py +5 -5
- ansible/module_utils/facts/namespace.py +1 -1
- ansible/module_utils/facts/network/base.py +1 -1
- ansible/module_utils/facts/network/fc_wwn.py +1 -2
- ansible/module_utils/facts/network/iscsi.py +1 -2
- ansible/module_utils/facts/network/nvme.py +1 -2
- ansible/module_utils/facts/other/facter.py +2 -3
- ansible/module_utils/facts/other/ohai.py +2 -3
- ansible/module_utils/facts/sysctl.py +4 -6
- ansible/module_utils/facts/system/apparmor.py +1 -2
- ansible/module_utils/facts/system/caps.py +3 -3
- ansible/module_utils/facts/system/chroot.py +1 -2
- ansible/module_utils/facts/system/cmdline.py +1 -2
- ansible/module_utils/facts/system/date_time.py +5 -3
- ansible/module_utils/facts/system/distribution.py +27 -13
- ansible/module_utils/facts/system/dns.py +1 -1
- ansible/module_utils/facts/system/env.py +1 -2
- ansible/module_utils/facts/system/fips.py +7 -20
- ansible/module_utils/facts/system/loadavg.py +1 -2
- ansible/module_utils/facts/system/local.py +2 -3
- ansible/module_utils/facts/system/lsb.py +1 -2
- ansible/module_utils/facts/system/pkg_mgr.py +1 -2
- ansible/module_utils/facts/system/platform.py +1 -2
- ansible/module_utils/facts/system/python.py +1 -2
- ansible/module_utils/facts/system/selinux.py +1 -1
- ansible/module_utils/facts/system/service_mgr.py +1 -2
- ansible/module_utils/facts/system/ssh_pub_keys.py +1 -1
- ansible/module_utils/facts/system/systemd.py +1 -1
- ansible/module_utils/facts/system/user.py +1 -2
- ansible/module_utils/facts/utils.py +3 -3
- ansible/module_utils/facts/virtual/base.py +1 -1
- ansible/module_utils/facts/virtual/linux.py +3 -3
- ansible/module_utils/facts/virtual/sunos.py +3 -15
- ansible/module_utils/facts/virtual/sysctl.py +3 -16
- ansible/module_utils/json_utils.py +2 -2
- ansible/module_utils/parsing/convert_bool.py +7 -1
- ansible/module_utils/powershell/Ansible.ModuleUtils.AddType.psm1 +1 -1
- ansible/module_utils/powershell/Ansible.ModuleUtils.CamelConversion.psm1 +1 -1
- ansible/module_utils/powershell/Ansible.ModuleUtils.CommandUtil.psm1 +1 -1
- ansible/module_utils/powershell/Ansible.ModuleUtils.WebRequest.psm1 +1 -1
- ansible/module_utils/service.py +21 -31
- ansible/module_utils/splitter.py +7 -7
- ansible/module_utils/testing.py +31 -0
- ansible/module_utils/urls.py +64 -35
- ansible/modules/add_host.py +4 -4
- ansible/modules/apt.py +69 -49
- ansible/modules/apt_key.py +19 -12
- ansible/modules/apt_repository.py +32 -51
- ansible/modules/assemble.py +16 -14
- ansible/modules/assert.py +4 -4
- ansible/modules/async_status.py +24 -24
- ansible/modules/async_wrapper.py +20 -25
- ansible/modules/blockinfile.py +6 -7
- ansible/modules/command.py +13 -20
- ansible/modules/copy.py +60 -147
- ansible/modules/cron.py +24 -21
- ansible/modules/deb822_repository.py +8 -9
- ansible/modules/debconf.py +5 -5
- ansible/modules/debug.py +4 -4
- ansible/modules/dnf.py +8 -8
- ansible/modules/dnf5.py +39 -13
- ansible/modules/dpkg_selections.py +4 -4
- ansible/modules/expect.py +13 -15
- ansible/modules/fail.py +4 -4
- ansible/modules/fetch.py +4 -4
- ansible/modules/file.py +184 -144
- ansible/modules/find.py +22 -20
- ansible/modules/gather_facts.py +3 -3
- ansible/modules/get_url.py +77 -54
- ansible/modules/getent.py +7 -9
- ansible/modules/git.py +38 -38
- ansible/modules/group.py +6 -6
- ansible/modules/group_by.py +4 -4
- ansible/modules/hostname.py +15 -32
- ansible/modules/import_playbook.py +6 -6
- ansible/modules/import_role.py +6 -6
- ansible/modules/import_tasks.py +6 -6
- ansible/modules/include_role.py +6 -6
- ansible/modules/include_tasks.py +6 -6
- ansible/modules/include_vars.py +6 -6
- ansible/modules/iptables.py +86 -73
- ansible/modules/known_hosts.py +22 -24
- ansible/modules/lineinfile.py +5 -5
- ansible/modules/meta.py +4 -4
- ansible/modules/mount_facts.py +2 -2
- ansible/modules/package.py +10 -4
- ansible/modules/package_facts.py +22 -10
- ansible/modules/pause.py +6 -6
- ansible/modules/ping.py +6 -6
- ansible/modules/pip.py +21 -26
- ansible/modules/raw.py +6 -6
- ansible/modules/reboot.py +6 -6
- ansible/modules/replace.py +10 -14
- ansible/modules/rpm_key.py +7 -8
- ansible/modules/script.py +4 -4
- ansible/modules/service.py +10 -17
- ansible/modules/service_facts.py +87 -10
- ansible/modules/set_fact.py +5 -5
- ansible/modules/set_stats.py +4 -4
- ansible/modules/setup.py +2 -2
- ansible/modules/shell.py +6 -6
- ansible/modules/slurp.py +16 -19
- ansible/modules/stat.py +15 -31
- ansible/modules/subversion.py +15 -15
- ansible/modules/systemd.py +7 -7
- ansible/modules/systemd_service.py +7 -7
- ansible/modules/sysvinit.py +9 -9
- ansible/modules/tempfile.py +5 -6
- ansible/modules/template.py +6 -6
- ansible/modules/unarchive.py +38 -17
- ansible/modules/uri.py +33 -26
- ansible/modules/user.py +45 -32
- ansible/modules/validate_argument_spec.py +10 -7
- ansible/modules/wait_for.py +70 -60
- ansible/modules/wait_for_connection.py +6 -6
- ansible/modules/yum_repository.py +10 -9
- ansible/parsing/ajson.py +17 -37
- ansible/parsing/dataloader.py +99 -54
- ansible/parsing/mod_args.py +62 -60
- ansible/parsing/plugin_docs.py +21 -86
- ansible/parsing/quoting.py +1 -1
- ansible/parsing/splitter.py +27 -12
- ansible/parsing/utils/addresses.py +24 -24
- ansible/parsing/utils/jsonify.py +5 -1
- ansible/parsing/utils/yaml.py +32 -61
- ansible/parsing/vault/__init__.py +327 -99
- ansible/parsing/yaml/__init__.py +0 -18
- ansible/parsing/yaml/dumper.py +6 -120
- ansible/parsing/yaml/loader.py +6 -39
- ansible/parsing/yaml/objects.py +43 -335
- ansible/playbook/__init__.py +1 -1
- ansible/playbook/attribute.py +8 -3
- ansible/playbook/base.py +187 -134
- ansible/playbook/block.py +26 -24
- ansible/playbook/collectionsearch.py +1 -15
- ansible/playbook/conditional.py +3 -77
- ansible/playbook/handler.py +8 -2
- ansible/playbook/helpers.py +41 -53
- ansible/playbook/included_file.py +32 -26
- ansible/playbook/loop_control.py +2 -2
- ansible/playbook/play.py +85 -44
- ansible/playbook/play_context.py +14 -17
- ansible/playbook/playbook_include.py +27 -62
- ansible/playbook/role/__init__.py +64 -49
- ansible/playbook/role/definition.py +15 -17
- ansible/playbook/role/include.py +2 -4
- ansible/playbook/role/metadata.py +10 -11
- ansible/playbook/role_include.py +3 -3
- ansible/playbook/taggable.py +28 -12
- ansible/playbook/task.py +192 -121
- ansible/playbook/task_include.py +5 -5
- ansible/plugins/__init__.py +58 -26
- ansible/plugins/action/__init__.py +188 -186
- ansible/plugins/action/add_host.py +2 -2
- ansible/plugins/action/assemble.py +11 -18
- ansible/plugins/action/assert.py +55 -67
- ansible/plugins/action/async_status.py +7 -2
- ansible/plugins/action/copy.py +14 -17
- ansible/plugins/action/debug.py +37 -31
- ansible/plugins/action/dnf.py +3 -4
- ansible/plugins/action/fail.py +1 -1
- ansible/plugins/action/fetch.py +7 -8
- ansible/plugins/action/gather_facts.py +13 -14
- ansible/plugins/action/group_by.py +1 -1
- ansible/plugins/action/include_vars.py +10 -11
- ansible/plugins/action/package.py +8 -14
- ansible/plugins/action/pause.py +2 -2
- ansible/plugins/action/script.py +27 -38
- ansible/plugins/action/service.py +9 -18
- ansible/plugins/action/set_fact.py +3 -12
- ansible/plugins/action/set_stats.py +3 -8
- ansible/plugins/action/template.py +47 -67
- ansible/plugins/action/unarchive.py +6 -16
- ansible/plugins/action/uri.py +9 -20
- ansible/plugins/action/validate_argument_spec.py +5 -5
- ansible/plugins/action/wait_for_connection.py +1 -1
- ansible/plugins/become/__init__.py +31 -8
- ansible/plugins/become/runas.py +71 -0
- ansible/plugins/become/su.py +13 -8
- ansible/plugins/become/sudo.py +19 -0
- ansible/plugins/cache/__init__.py +52 -63
- ansible/plugins/cache/base.py +8 -0
- ansible/plugins/cache/jsonfile.py +10 -16
- ansible/plugins/cache/memory.py +6 -12
- ansible/plugins/callback/__init__.py +294 -201
- ansible/plugins/callback/default.py +99 -95
- ansible/plugins/callback/junit.py +44 -43
- ansible/plugins/callback/minimal.py +28 -25
- ansible/plugins/callback/oneline.py +34 -21
- ansible/plugins/callback/tree.py +27 -16
- ansible/plugins/connection/__init__.py +47 -34
- ansible/plugins/connection/local.py +156 -60
- ansible/plugins/connection/paramiko_ssh.py +34 -24
- ansible/plugins/connection/psrp.py +76 -165
- ansible/plugins/connection/ssh.py +326 -86
- ansible/plugins/connection/winrm.py +62 -141
- ansible/plugins/doc_fragments/action_common_attributes.py +14 -14
- ansible/plugins/doc_fragments/action_core.py +6 -6
- ansible/plugins/doc_fragments/backup.py +2 -2
- ansible/plugins/doc_fragments/checksum_common.py +27 -0
- ansible/plugins/doc_fragments/constructed.py +8 -4
- ansible/plugins/doc_fragments/decrypt.py +2 -2
- ansible/plugins/doc_fragments/default_callback.py +2 -2
- ansible/plugins/doc_fragments/files.py +2 -2
- ansible/plugins/doc_fragments/inventory_cache.py +2 -2
- ansible/plugins/doc_fragments/result_format_callback.py +2 -2
- ansible/plugins/doc_fragments/return_common.py +2 -2
- ansible/plugins/doc_fragments/template_common.py +4 -4
- ansible/plugins/doc_fragments/url.py +17 -1
- ansible/plugins/doc_fragments/url_windows.py +2 -2
- ansible/plugins/doc_fragments/validate.py +2 -2
- ansible/plugins/doc_fragments/vars_plugin_staging.py +2 -2
- ansible/plugins/filter/__init__.py +6 -2
- ansible/plugins/filter/b64decode.yml +22 -0
- ansible/plugins/filter/b64encode.yml +22 -0
- ansible/plugins/filter/bool.yml +11 -4
- ansible/plugins/filter/core.py +245 -120
- ansible/plugins/filter/encryption.py +42 -34
- ansible/plugins/filter/flatten.yml +3 -2
- ansible/plugins/filter/human_to_bytes.yml +1 -1
- ansible/plugins/filter/mathstuff.py +30 -37
- ansible/plugins/filter/password_hash.yml +8 -0
- ansible/plugins/filter/pow.yml +1 -1
- ansible/plugins/filter/regex_search.yml +1 -4
- ansible/plugins/filter/root.yml +1 -1
- ansible/plugins/filter/split.yml +1 -1
- ansible/plugins/filter/strftime.yml +3 -3
- ansible/plugins/filter/to_nice_yaml.yml +0 -4
- ansible/plugins/filter/to_uuid.yml +1 -1
- ansible/plugins/filter/to_yaml.yml +0 -4
- ansible/plugins/filter/unvault.yml +1 -1
- ansible/plugins/filter/urls.py +1 -1
- ansible/plugins/filter/urlsplit.py +8 -9
- ansible/plugins/filter/vault.yml +14 -9
- ansible/plugins/filter/win_basename.yml +6 -1
- ansible/plugins/filter/win_dirname.yml +5 -0
- ansible/plugins/inventory/__init__.py +107 -86
- ansible/plugins/inventory/advanced_host_list.py +7 -5
- ansible/plugins/inventory/auto.py +11 -4
- ansible/plugins/inventory/constructed.py +21 -24
- ansible/plugins/inventory/generator.py +16 -11
- ansible/plugins/inventory/host_list.py +7 -5
- ansible/plugins/inventory/ini.py +78 -44
- ansible/plugins/inventory/script.py +190 -120
- ansible/plugins/inventory/toml.py +16 -126
- ansible/plugins/inventory/yaml.py +10 -8
- ansible/plugins/list.py +72 -19
- ansible/plugins/loader.py +383 -198
- ansible/plugins/lookup/__init__.py +21 -4
- ansible/plugins/lookup/config.py +21 -35
- ansible/plugins/lookup/csvfile.py +19 -73
- ansible/plugins/lookup/dict.py +1 -6
- ansible/plugins/lookup/env.py +12 -9
- ansible/plugins/lookup/file.py +5 -8
- ansible/plugins/lookup/first_found.py +87 -55
- ansible/plugins/lookup/indexed_items.py +1 -10
- ansible/plugins/lookup/ini.py +14 -13
- ansible/plugins/lookup/items.py +1 -1
- ansible/plugins/lookup/lines.py +8 -1
- ansible/plugins/lookup/list.py +1 -1
- ansible/plugins/lookup/nested.py +2 -18
- ansible/plugins/lookup/password.py +5 -5
- ansible/plugins/lookup/pipe.py +5 -7
- ansible/plugins/lookup/sequence.py +18 -8
- ansible/plugins/lookup/subelements.py +1 -4
- ansible/plugins/lookup/template.py +47 -36
- ansible/plugins/lookup/together.py +0 -12
- ansible/plugins/lookup/unvault.py +1 -5
- ansible/plugins/lookup/url.py +4 -10
- ansible/plugins/lookup/vars.py +16 -24
- ansible/plugins/shell/__init__.py +58 -4
- ansible/plugins/shell/cmd.py +2 -2
- ansible/plugins/shell/powershell.py +106 -31
- ansible/plugins/shell/sh.py +13 -7
- ansible/plugins/strategy/__init__.py +168 -193
- ansible/plugins/strategy/debug.py +2 -2
- ansible/plugins/strategy/free.py +16 -31
- ansible/plugins/strategy/host_pinned.py +2 -2
- ansible/plugins/strategy/linear.py +41 -41
- ansible/plugins/terminal/__init__.py +4 -4
- ansible/plugins/test/__init__.py +7 -2
- ansible/plugins/test/core.py +75 -35
- ansible/plugins/test/files.py +1 -1
- ansible/plugins/test/finished.yml +1 -1
- ansible/plugins/test/mathstuff.py +3 -3
- ansible/plugins/test/uri.py +5 -8
- ansible/plugins/vars/host_group_vars.py +7 -14
- ansible/release.py +2 -2
- ansible/template/__init__.py +353 -943
- ansible/utils/__init__.py +0 -18
- ansible/utils/collection_loader/__init__.py +54 -5
- ansible/utils/collection_loader/_collection_config.py +5 -6
- ansible/utils/collection_loader/_collection_finder.py +82 -96
- ansible/utils/collection_loader/_collection_meta.py +15 -8
- ansible/utils/display.py +485 -73
- ansible/utils/encrypt.py +27 -19
- ansible/utils/fqcn.py +2 -2
- ansible/utils/galaxy.py +2 -2
- ansible/utils/hashing.py +8 -10
- ansible/utils/helpers.py +2 -2
- ansible/utils/listify.py +10 -8
- ansible/utils/lock.py +2 -2
- ansible/utils/path.py +10 -12
- ansible/utils/plugin_docs.py +16 -14
- ansible/utils/py3compat.py +2 -7
- ansible/utils/sentinel.py +4 -62
- ansible/utils/singleton.py +2 -0
- ansible/utils/ssh_functions.py +6 -2
- ansible/utils/unsafe_proxy.py +23 -332
- ansible/utils/vars.py +55 -8
- ansible/utils/version.py +2 -2
- ansible/vars/clean.py +5 -5
- ansible/vars/hostvars.py +60 -90
- ansible/vars/manager.py +220 -285
- ansible/vars/plugins.py +4 -4
- ansible/vars/reserved.py +13 -12
- {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/METADATA +4 -3
- ansible_core-2.19.0.dist-info/RECORD +1097 -0
- ansible_core-2.19.0.dist-info/licenses/licenses/BSD-3-Clause.txt +28 -0
- ansible_test/_data/completion/docker.txt +7 -7
- ansible_test/_data/completion/remote.txt +6 -6
- ansible_test/_data/completion/windows.txt +1 -0
- ansible_test/_data/requirements/ansible.txt +2 -2
- ansible_test/_data/requirements/sanity.ansible-doc.txt +3 -3
- ansible_test/_data/requirements/sanity.changelog.txt +2 -2
- ansible_test/_data/requirements/sanity.import.plugin.txt +2 -2
- ansible_test/_data/requirements/sanity.pep8.txt +1 -1
- ansible_test/_data/requirements/sanity.pylint.txt +5 -5
- ansible_test/_data/requirements/sanity.validate-modules.txt +2 -2
- ansible_test/_data/requirements/sanity.yamllint.txt +1 -1
- ansible_test/_data/requirements/units.txt +1 -0
- ansible_test/_internal/__init__.py +6 -0
- ansible_test/_internal/ansible_util.py +3 -1
- ansible_test/_internal/become.py +1 -0
- ansible_test/_internal/bootstrap.py +1 -0
- ansible_test/_internal/cache.py +1 -0
- ansible_test/_internal/cgroup.py +1 -0
- ansible_test/_internal/ci/__init__.py +1 -0
- ansible_test/_internal/ci/azp.py +1 -0
- ansible_test/_internal/ci/local.py +1 -0
- ansible_test/_internal/classification/__init__.py +1 -0
- ansible_test/_internal/classification/common.py +1 -0
- ansible_test/_internal/classification/csharp.py +1 -0
- ansible_test/_internal/classification/powershell.py +1 -0
- ansible_test/_internal/classification/python.py +1 -0
- ansible_test/_internal/cli/__init__.py +1 -0
- ansible_test/_internal/cli/actions.py +1 -0
- ansible_test/_internal/cli/argparsing/__init__.py +1 -0
- ansible_test/_internal/cli/argparsing/actions.py +1 -0
- ansible_test/_internal/cli/argparsing/argcompletion.py +1 -0
- ansible_test/_internal/cli/argparsing/parsers.py +1 -0
- ansible_test/_internal/cli/commands/__init__.py +11 -5
- ansible_test/_internal/cli/commands/coverage/__init__.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/__init__.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/__init__.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/combine.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/expand.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/filter.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/generate.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/missing.py +1 -0
- ansible_test/_internal/cli/commands/coverage/combine.py +1 -0
- ansible_test/_internal/cli/commands/coverage/erase.py +1 -0
- ansible_test/_internal/cli/commands/coverage/html.py +1 -0
- ansible_test/_internal/cli/commands/coverage/report.py +1 -0
- ansible_test/_internal/cli/commands/coverage/xml.py +1 -0
- ansible_test/_internal/cli/commands/env.py +1 -0
- ansible_test/_internal/cli/commands/integration/__init__.py +1 -0
- ansible_test/_internal/cli/commands/integration/network.py +1 -0
- ansible_test/_internal/cli/commands/integration/posix.py +1 -0
- ansible_test/_internal/cli/commands/integration/windows.py +1 -0
- ansible_test/_internal/cli/commands/sanity.py +9 -0
- ansible_test/_internal/cli/commands/shell.py +1 -0
- ansible_test/_internal/cli/commands/units.py +1 -0
- ansible_test/_internal/cli/compat.py +1 -0
- ansible_test/_internal/cli/completers.py +1 -0
- ansible_test/_internal/cli/converters.py +1 -0
- ansible_test/_internal/cli/environments.py +52 -5
- ansible_test/_internal/cli/epilog.py +1 -0
- ansible_test/_internal/cli/parsers/__init__.py +1 -0
- ansible_test/_internal/cli/parsers/base_argument_parsers.py +1 -0
- ansible_test/_internal/cli/parsers/helpers.py +1 -0
- ansible_test/_internal/cli/parsers/host_config_parsers.py +1 -0
- ansible_test/_internal/cli/parsers/key_value_parsers.py +1 -0
- ansible_test/_internal/cli/parsers/value_parsers.py +1 -0
- ansible_test/_internal/commands/__init__.py +1 -0
- ansible_test/_internal/commands/coverage/__init__.py +3 -2
- ansible_test/_internal/commands/coverage/analyze/__init__.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/__init__.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/combine.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/expand.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/filter.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/generate.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/missing.py +1 -0
- ansible_test/_internal/commands/coverage/combine.py +2 -1
- ansible_test/_internal/commands/coverage/erase.py +1 -0
- ansible_test/_internal/commands/coverage/html.py +1 -0
- ansible_test/_internal/commands/coverage/report.py +1 -0
- ansible_test/_internal/commands/coverage/xml.py +1 -0
- ansible_test/_internal/commands/env/__init__.py +2 -0
- ansible_test/_internal/commands/integration/__init__.py +22 -5
- ansible_test/_internal/commands/integration/cloud/__init__.py +1 -0
- ansible_test/_internal/commands/integration/cloud/acme.py +2 -1
- ansible_test/_internal/commands/integration/cloud/aws.py +1 -0
- ansible_test/_internal/commands/integration/cloud/azure.py +1 -0
- ansible_test/_internal/commands/integration/cloud/cs.py +1 -0
- ansible_test/_internal/commands/integration/cloud/digitalocean.py +1 -0
- ansible_test/_internal/commands/integration/cloud/galaxy.py +3 -2
- ansible_test/_internal/commands/integration/cloud/hcloud.py +1 -0
- ansible_test/_internal/commands/integration/cloud/httptester.py +3 -2
- ansible_test/_internal/commands/integration/cloud/nios.py +2 -1
- ansible_test/_internal/commands/integration/cloud/opennebula.py +1 -0
- ansible_test/_internal/commands/integration/cloud/openshift.py +1 -0
- ansible_test/_internal/commands/integration/cloud/scaleway.py +1 -0
- ansible_test/_internal/commands/integration/cloud/vcenter.py +1 -0
- ansible_test/_internal/commands/integration/cloud/vultr.py +1 -0
- ansible_test/_internal/commands/integration/coverage.py +8 -2
- ansible_test/_internal/commands/integration/filters.py +1 -0
- ansible_test/_internal/commands/integration/network.py +1 -0
- ansible_test/_internal/commands/integration/posix.py +1 -0
- ansible_test/_internal/commands/integration/windows.py +1 -0
- ansible_test/_internal/commands/sanity/__init__.py +19 -2
- ansible_test/_internal/commands/sanity/ansible_doc.py +1 -0
- ansible_test/_internal/commands/sanity/bin_symlinks.py +1 -0
- ansible_test/_internal/commands/sanity/compile.py +1 -0
- ansible_test/_internal/commands/sanity/ignores.py +1 -0
- ansible_test/_internal/commands/sanity/import.py +1 -0
- ansible_test/_internal/commands/sanity/integration_aliases.py +12 -0
- ansible_test/_internal/commands/sanity/pep8.py +1 -0
- ansible_test/_internal/commands/sanity/pslint.py +1 -0
- ansible_test/_internal/commands/sanity/pylint.py +25 -26
- ansible_test/_internal/commands/sanity/shellcheck.py +1 -0
- ansible_test/_internal/commands/sanity/validate_modules.py +1 -0
- ansible_test/_internal/commands/sanity/yamllint.py +1 -0
- ansible_test/_internal/commands/shell/__init__.py +44 -4
- ansible_test/_internal/commands/units/__init__.py +5 -1
- ansible_test/_internal/compat/__init__.py +1 -0
- ansible_test/_internal/compat/packaging.py +1 -0
- ansible_test/_internal/compat/yaml.py +1 -0
- ansible_test/_internal/completion.py +1 -0
- ansible_test/_internal/config.py +23 -13
- ansible_test/_internal/connections.py +1 -0
- ansible_test/_internal/constants.py +1 -0
- ansible_test/_internal/containers.py +1 -0
- ansible_test/_internal/content_config.py +1 -0
- ansible_test/_internal/core_ci.py +1 -0
- ansible_test/_internal/coverage_util.py +11 -10
- ansible_test/_internal/data.py +1 -0
- ansible_test/_internal/debugging.py +166 -0
- ansible_test/_internal/delegation.py +22 -13
- ansible_test/_internal/dev/__init__.py +1 -0
- ansible_test/_internal/dev/container_probe.py +1 -0
- ansible_test/_internal/diff.py +3 -2
- ansible_test/_internal/docker_util.py +2 -1
- ansible_test/_internal/encoding.py +1 -0
- ansible_test/_internal/executor.py +1 -0
- ansible_test/_internal/git.py +1 -0
- ansible_test/_internal/host_configs.py +1 -0
- ansible_test/_internal/host_profiles.py +260 -16
- ansible_test/_internal/http.py +1 -0
- ansible_test/_internal/init.py +1 -0
- ansible_test/_internal/inventory.py +39 -3
- ansible_test/_internal/io.py +1 -0
- ansible_test/_internal/metadata.py +95 -4
- ansible_test/_internal/payload.py +1 -0
- ansible_test/_internal/processes.py +80 -0
- ansible_test/_internal/provider/__init__.py +1 -0
- ansible_test/_internal/provider/layout/__init__.py +1 -0
- ansible_test/_internal/provider/layout/ansible.py +1 -0
- ansible_test/_internal/provider/layout/collection.py +1 -0
- ansible_test/_internal/provider/layout/unsupported.py +1 -0
- ansible_test/_internal/provider/source/__init__.py +1 -0
- ansible_test/_internal/provider/source/git.py +1 -0
- ansible_test/_internal/provider/source/installed.py +1 -0
- ansible_test/_internal/provider/source/unsupported.py +1 -0
- ansible_test/_internal/provider/source/unversioned.py +1 -0
- ansible_test/_internal/provisioning.py +11 -4
- ansible_test/_internal/pypi_proxy.py +6 -5
- ansible_test/_internal/python_requirements.py +28 -0
- ansible_test/_internal/ssh.py +2 -5
- ansible_test/_internal/target.py +9 -0
- ansible_test/_internal/test.py +3 -2
- ansible_test/_internal/thread.py +3 -1
- ansible_test/_internal/timeout.py +2 -1
- ansible_test/_internal/util.py +41 -12
- ansible_test/_internal/util_common.py +18 -5
- ansible_test/_internal/venv.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/action-plugin-docs.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/changelog/sphinx.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/changelog.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/empty-init.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/line-endings.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-assert.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-get-exception.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-illegal-filenames.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-smart-quotes.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/replace-urlopen.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/runtime-metadata.py +28 -1
- ansible_test/_util/controller/sanity/code-smell/shebang.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/symlinks.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/use-argspec-type-path.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/use-compat-six.py +1 -0
- ansible_test/_util/controller/sanity/integration-aliases/yaml_to_json.py +2 -1
- ansible_test/_util/controller/sanity/pep8/current-ignore.txt +4 -0
- ansible_test/_util/controller/sanity/pylint/config/ansible-test-target.cfg +8 -5
- ansible_test/_util/controller/sanity/pylint/config/ansible-test.cfg +8 -5
- ansible_test/_util/controller/sanity/pylint/config/code-smell.cfg +8 -5
- ansible_test/_util/controller/sanity/pylint/config/collection.cfg +4 -5
- ansible_test/_util/controller/sanity/pylint/config/default.cfg +8 -7
- ansible_test/_util/controller/sanity/pylint/plugins/deprecated_calls.py +541 -0
- ansible_test/_util/controller/sanity/pylint/plugins/deprecated_comment.py +137 -0
- ansible_test/_util/controller/sanity/pylint/plugins/hide_unraisable.py +1 -0
- ansible_test/_util/controller/sanity/pylint/plugins/string_format.py +1 -8
- ansible_test/_util/controller/sanity/pylint/plugins/unwanted.py +1 -8
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py +55 -28
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/module_args.py +12 -5
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/schema.py +13 -2
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/utils.py +1 -0
- ansible_test/_util/controller/sanity/yamllint/yamllinter.py +35 -17
- ansible_test/_util/controller/tools/collection_detail.py +1 -0
- ansible_test/_util/controller/tools/yaml_to_json.py +2 -1
- ansible_test/_util/target/injector/python.py +8 -0
- ansible_test/_util/target/pytest/plugins/ansible_forked.py +6 -1
- ansible_test/_util/target/pytest/plugins/ansible_pytest_collections.py +2 -1
- ansible_test/_util/target/pytest/plugins/ansible_pytest_coverage.py +1 -0
- ansible_test/_util/target/sanity/compile/compile.py +1 -0
- ansible_test/_util/target/sanity/import/importer.py +15 -16
- ansible_test/_util/target/setup/bootstrap.sh +9 -20
- ansible_test/_util/target/setup/probe_cgroups.py +1 -0
- ansible_test/_util/target/setup/quiet_pip.py +1 -0
- ansible_test/_util/target/setup/requirements.py +38 -36
- ansible_test/_util/target/tools/virtualenvcheck.py +2 -1
- ansible_test/_util/target/tools/yamlcheck.py +2 -1
- ansible/compat/selectors.py +0 -32
- ansible/errors/yaml_strings.py +0 -138
- ansible/executor/action_write_locks.py +0 -44
- ansible/executor/discovery/python_target.py +0 -47
- ansible/executor/powershell/module_powershell_wrapper.ps1 +0 -86
- ansible/executor/powershell/module_script_wrapper.ps1 +0 -22
- ansible/module_utils/compat/importlib.py +0 -26
- ansible/module_utils/compat/selectors.py +0 -32
- ansible/module_utils/pycompat24.py +0 -73
- ansible/parsing/yaml/constructor.py +0 -178
- ansible/template/native_helpers.py +0 -251
- ansible/template/template.py +0 -43
- ansible/template/vars.py +0 -77
- ansible/utils/native_jinja.py +0 -11
- ansible/vars/fact_cache.py +0 -71
- ansible_core-2.18.7rc1.dist-info/RECORD +0 -992
- ansible_test/_util/controller/sanity/pylint/plugins/deprecated.py +0 -411
- {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/WHEEL +0 -0
- {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/entry_points.txt +0 -0
- {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/COPYING +0 -0
- {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/Apache-License.txt +0 -0
- {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/MIT-license.txt +0 -0
- {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/PSF-license.txt +0 -0
- {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/simplified_bsd.txt +0 -0
- {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/top_level.txt +0 -0
ansible/config/manager.py
CHANGED
|
@@ -6,28 +6,28 @@ from __future__ import annotations
|
|
|
6
6
|
import atexit
|
|
7
7
|
import decimal
|
|
8
8
|
import configparser
|
|
9
|
+
import functools
|
|
9
10
|
import os
|
|
10
11
|
import os.path
|
|
11
12
|
import sys
|
|
12
13
|
import stat
|
|
13
14
|
import tempfile
|
|
15
|
+
import typing as t
|
|
14
16
|
|
|
15
|
-
from collections import namedtuple
|
|
16
17
|
from collections.abc import Mapping, Sequence
|
|
17
18
|
from jinja2.nativetypes import NativeEnvironment
|
|
18
19
|
|
|
19
|
-
from ansible.
|
|
20
|
+
from ansible._internal._datatag import _tags
|
|
21
|
+
from ansible.errors import AnsibleOptionsError, AnsibleError, AnsibleUndefinedConfigEntry, AnsibleRequiredOptionError
|
|
22
|
+
from ansible.module_utils._internal._datatag import AnsibleTagHelper
|
|
23
|
+
from ansible.module_utils.common.sentinel import Sentinel
|
|
20
24
|
from ansible.module_utils.common.text.converters import to_text, to_bytes, to_native
|
|
21
25
|
from ansible.module_utils.common.yaml import yaml_load
|
|
22
|
-
from ansible.module_utils.six import string_types
|
|
23
26
|
from ansible.module_utils.parsing.convert_bool import boolean
|
|
24
27
|
from ansible.parsing.quoting import unquote
|
|
25
|
-
from ansible.parsing.yaml.objects import AnsibleVaultEncryptedUnicode
|
|
26
28
|
from ansible.utils.path import cleanup_tmp_file, makedirs_safe, unfrackpath
|
|
27
29
|
|
|
28
30
|
|
|
29
|
-
Setting = namedtuple('Setting', 'name value origin type')
|
|
30
|
-
|
|
31
31
|
INTERNAL_DEFS = {'lookup': ('_terms',)}
|
|
32
32
|
|
|
33
33
|
GALAXY_SERVER_DEF = [
|
|
@@ -39,6 +39,7 @@ GALAXY_SERVER_DEF = [
|
|
|
39
39
|
('api_version', False, 'int'),
|
|
40
40
|
('validate_certs', False, 'bool'),
|
|
41
41
|
('client_id', False, 'str'),
|
|
42
|
+
('client_secret', False, 'str'),
|
|
42
43
|
('timeout', False, 'int'),
|
|
43
44
|
]
|
|
44
45
|
|
|
@@ -51,145 +52,181 @@ GALAXY_SERVER_ADDITIONAL = {
|
|
|
51
52
|
}
|
|
52
53
|
|
|
53
54
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
@t.runtime_checkable
|
|
56
|
+
class _EncryptedStringProtocol(t.Protocol):
|
|
57
|
+
"""Protocol representing an `EncryptedString`, since it cannot be imported here."""
|
|
58
|
+
# DTFIX-FUTURE: collapse this with the one in collection loader, once we can
|
|
59
|
+
|
|
60
|
+
def _decrypt(self) -> str: ...
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _get_config_label(plugin_type: str, plugin_name: str, config: str) -> str:
|
|
64
|
+
"""Return a label for the given config."""
|
|
65
|
+
entry = f'{config!r}'
|
|
66
|
+
|
|
57
67
|
if plugin_type:
|
|
58
|
-
entry += '
|
|
68
|
+
entry += ' for'
|
|
69
|
+
|
|
59
70
|
if plugin_name:
|
|
60
|
-
entry += '
|
|
61
|
-
|
|
71
|
+
entry += f' {plugin_name!r}'
|
|
72
|
+
|
|
73
|
+
entry += f' {plugin_type} plugin'
|
|
74
|
+
|
|
62
75
|
return entry
|
|
63
76
|
|
|
64
77
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
78
|
+
def ensure_type(value: object, value_type: str | None, origin: str | None = None, origin_ftype: str | None = None) -> t.Any:
|
|
79
|
+
"""
|
|
80
|
+
Converts `value` to the requested `value_type`; raises `ValueError` for failed conversions.
|
|
81
|
+
|
|
82
|
+
Values for `value_type` are:
|
|
83
|
+
|
|
84
|
+
* boolean/bool: Return a `bool` by applying non-strict `bool` filter rules:
|
|
85
|
+
'y', 'yes', 'on', '1', 'true', 't', 1, 1.0, True return True, any other value is False.
|
|
86
|
+
* integer/int: Return an `int`. Accepts any `str` parseable by `int` or numeric value with a zero mantissa (including `bool`).
|
|
87
|
+
* float: Return a `float`. Accepts any `str` parseable by `float` or numeric value (including `bool`).
|
|
88
|
+
* list: Return a `list`. Accepts `list` or `Sequence`. Also accepts, `str`, splitting on ',' while stripping whitespace and unquoting items.
|
|
89
|
+
* none: Return `None`. Accepts only the string "None".
|
|
90
|
+
* path: Return a resolved path. Accepts `str`.
|
|
91
|
+
* temppath/tmppath/tmp: Return a unique temporary directory inside the resolved path specified by the value.
|
|
92
|
+
* pathspec: Return a `list` of resolved paths. Accepts a `list` or `Sequence`. Also accepts `str`, splitting on ':'.
|
|
93
|
+
* pathlist: Return a `list` of resolved paths. Accepts a `list` or `Sequence`. Also accepts `str`, splitting on `,` while stripping whitespace from paths.
|
|
94
|
+
* dictionary/dict: Return a `dict`. Accepts `dict` or `Mapping`.
|
|
95
|
+
* string/str: Return a `str`. Accepts `bool`, `int`, `float`, `complex` or `str`.
|
|
96
|
+
|
|
97
|
+
Path resolution ensures paths are `str` with expansion of '{{CWD}}', environment variables and '~'.
|
|
98
|
+
Non-absolute paths are expanded relative to the basedir from `origin`, if specified.
|
|
99
|
+
|
|
100
|
+
No conversion is performed if `value_type` is unknown or `value` is `None`.
|
|
101
|
+
When `origin_ftype` is "ini", a `str` result will be unquoted.
|
|
102
|
+
"""
|
|
103
|
+
|
|
104
|
+
if value is None:
|
|
105
|
+
return None
|
|
106
|
+
|
|
107
|
+
original_value = value
|
|
108
|
+
copy_tags = value_type not in ('temppath', 'tmppath', 'tmp')
|
|
109
|
+
|
|
110
|
+
value = _ensure_type(value, value_type, origin)
|
|
111
|
+
|
|
112
|
+
if copy_tags and value is not original_value:
|
|
113
|
+
if isinstance(value, list):
|
|
114
|
+
value = [AnsibleTagHelper.tag_copy(original_value, item) for item in value]
|
|
115
|
+
|
|
116
|
+
value = AnsibleTagHelper.tag_copy(original_value, value)
|
|
117
|
+
|
|
118
|
+
if isinstance(value, str) and origin_ftype and origin_ftype == 'ini':
|
|
119
|
+
value = unquote(value)
|
|
120
|
+
|
|
121
|
+
return value
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def _ensure_type(value: object, value_type: str | None, origin: str | None = None) -> t.Any:
|
|
125
|
+
"""Internal implementation for `ensure_type`, call that function instead."""
|
|
126
|
+
original_value = value
|
|
127
|
+
basedir = origin if origin and os.path.isabs(origin) and os.path.exists(to_bytes(origin)) else None
|
|
96
128
|
|
|
97
129
|
if value_type:
|
|
98
130
|
value_type = value_type.lower()
|
|
99
131
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
132
|
+
match value_type:
|
|
133
|
+
case 'boolean' | 'bool':
|
|
134
|
+
return boolean(value, strict=False)
|
|
103
135
|
|
|
104
|
-
|
|
105
|
-
if
|
|
136
|
+
case 'integer' | 'int':
|
|
137
|
+
if isinstance(value, int): # handle both int and bool (which is an int)
|
|
138
|
+
return int(value)
|
|
139
|
+
|
|
140
|
+
if isinstance(value, (float, str)):
|
|
106
141
|
try:
|
|
142
|
+
# use Decimal for all other source type conversions; non-zero mantissa is a failure
|
|
107
143
|
if (decimal_value := decimal.Decimal(value)) == (int_part := int(decimal_value)):
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
except decimal.DecimalException as e:
|
|
112
|
-
raise ValueError from e
|
|
144
|
+
return int_part
|
|
145
|
+
except (decimal.DecimalException, ValueError):
|
|
146
|
+
pass
|
|
113
147
|
|
|
114
|
-
|
|
115
|
-
if
|
|
116
|
-
|
|
148
|
+
case 'float':
|
|
149
|
+
if isinstance(value, float):
|
|
150
|
+
return value
|
|
117
151
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
152
|
+
if isinstance(value, (int, str)):
|
|
153
|
+
try:
|
|
154
|
+
return float(value)
|
|
155
|
+
except ValueError:
|
|
156
|
+
pass
|
|
157
|
+
|
|
158
|
+
case 'list':
|
|
159
|
+
if isinstance(value, list):
|
|
160
|
+
return value
|
|
161
|
+
|
|
162
|
+
if isinstance(value, str):
|
|
163
|
+
return [unquote(x.strip()) for x in value.split(',')]
|
|
164
|
+
|
|
165
|
+
if isinstance(value, Sequence) and not isinstance(value, bytes):
|
|
166
|
+
return list(value)
|
|
123
167
|
|
|
124
|
-
|
|
168
|
+
case 'none':
|
|
125
169
|
if value == "None":
|
|
126
|
-
|
|
170
|
+
return None
|
|
127
171
|
|
|
128
|
-
|
|
129
|
-
|
|
172
|
+
case 'path':
|
|
173
|
+
if isinstance(value, str):
|
|
174
|
+
return resolve_path(value, basedir=basedir)
|
|
130
175
|
|
|
131
|
-
|
|
132
|
-
if isinstance(value,
|
|
176
|
+
case 'temppath' | 'tmppath' | 'tmp':
|
|
177
|
+
if isinstance(value, str):
|
|
133
178
|
value = resolve_path(value, basedir=basedir)
|
|
134
|
-
else:
|
|
135
|
-
errmsg = 'path'
|
|
136
179
|
|
|
137
|
-
elif value_type in ('tmp', 'temppath', 'tmppath'):
|
|
138
|
-
if isinstance(value, string_types):
|
|
139
|
-
value = resolve_path(value, basedir=basedir)
|
|
140
180
|
if not os.path.exists(value):
|
|
141
181
|
makedirs_safe(value, 0o700)
|
|
182
|
+
|
|
142
183
|
prefix = 'ansible-local-%s' % os.getpid()
|
|
143
184
|
value = tempfile.mkdtemp(prefix=prefix, dir=value)
|
|
144
185
|
atexit.register(cleanup_tmp_file, value, warn=True)
|
|
145
|
-
else:
|
|
146
|
-
errmsg = 'temppath'
|
|
147
186
|
|
|
148
|
-
|
|
149
|
-
|
|
187
|
+
return value
|
|
188
|
+
|
|
189
|
+
case 'pathspec':
|
|
190
|
+
if isinstance(value, str):
|
|
150
191
|
value = value.split(os.pathsep)
|
|
151
192
|
|
|
152
|
-
if isinstance(value, Sequence):
|
|
153
|
-
|
|
154
|
-
else:
|
|
155
|
-
errmsg = 'pathspec'
|
|
193
|
+
if isinstance(value, Sequence) and not isinstance(value, bytes) and all(isinstance(x, str) for x in value):
|
|
194
|
+
return [resolve_path(x, basedir=basedir) for x in value]
|
|
156
195
|
|
|
157
|
-
|
|
158
|
-
if isinstance(value,
|
|
196
|
+
case 'pathlist':
|
|
197
|
+
if isinstance(value, str):
|
|
159
198
|
value = [x.strip() for x in value.split(',')]
|
|
160
199
|
|
|
161
|
-
if isinstance(value, Sequence):
|
|
162
|
-
|
|
163
|
-
else:
|
|
164
|
-
errmsg = 'pathlist'
|
|
200
|
+
if isinstance(value, Sequence) and not isinstance(value, bytes) and all(isinstance(x, str) for x in value):
|
|
201
|
+
return [resolve_path(x, basedir=basedir) for x in value]
|
|
165
202
|
|
|
166
|
-
|
|
167
|
-
if
|
|
168
|
-
|
|
203
|
+
case 'dictionary' | 'dict':
|
|
204
|
+
if isinstance(value, dict):
|
|
205
|
+
return value
|
|
169
206
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
errmsg = 'string'
|
|
207
|
+
if isinstance(value, Mapping):
|
|
208
|
+
return dict(value)
|
|
209
|
+
|
|
210
|
+
case 'string' | 'str':
|
|
211
|
+
if isinstance(value, str):
|
|
212
|
+
return value
|
|
177
213
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
value = to_text(value, errors='surrogate_or_strict')
|
|
181
|
-
if origin_ftype and origin_ftype == 'ini':
|
|
182
|
-
value = unquote(value)
|
|
214
|
+
if isinstance(value, (bool, int, float, complex)):
|
|
215
|
+
return str(value)
|
|
183
216
|
|
|
184
|
-
|
|
185
|
-
|
|
217
|
+
if isinstance(value, _EncryptedStringProtocol):
|
|
218
|
+
return value._decrypt()
|
|
186
219
|
|
|
187
|
-
|
|
220
|
+
case _:
|
|
221
|
+
# FIXME: define and document a pass-through value_type (None, 'raw', 'object', '', ...) and then deprecate acceptance of unknown types
|
|
222
|
+
return value # return non-str values of unknown value_type as-is
|
|
223
|
+
|
|
224
|
+
raise ValueError(f'Invalid value provided for {value_type!r}: {original_value!r}')
|
|
188
225
|
|
|
189
226
|
|
|
190
227
|
# FIXME: see if this can live in utils/path
|
|
191
|
-
def resolve_path(path, basedir=None):
|
|
192
|
-
|
|
228
|
+
def resolve_path(path: str, basedir: str | None = None) -> str:
|
|
229
|
+
""" resolve relative or 'variable' paths """
|
|
193
230
|
if '{{CWD}}' in path: # allow users to force CWD using 'magic' {{CWD}}
|
|
194
231
|
path = path.replace('{{CWD}}', os.getcwd())
|
|
195
232
|
|
|
@@ -212,35 +249,21 @@ def get_config_type(cfile):
|
|
|
212
249
|
return ftype
|
|
213
250
|
|
|
214
251
|
|
|
215
|
-
# FIXME: can move to module_utils for use for ini plugins also?
|
|
216
|
-
def get_ini_config_value(p, entry):
|
|
217
|
-
''' returns the value of last ini entry found '''
|
|
218
|
-
value = None
|
|
219
|
-
if p is not None:
|
|
220
|
-
try:
|
|
221
|
-
value = p.get(entry.get('section', 'defaults'), entry.get('key', ''), raw=True)
|
|
222
|
-
except Exception: # FIXME: actually report issues here
|
|
223
|
-
pass
|
|
224
|
-
return value
|
|
225
|
-
|
|
226
|
-
|
|
227
252
|
def find_ini_config_file(warnings=None):
|
|
228
|
-
|
|
253
|
+
""" Load INI Config File order(first found is used): ENV, CWD, HOME, /etc/ansible """
|
|
229
254
|
# FIXME: eventually deprecate ini configs
|
|
230
255
|
|
|
231
256
|
if warnings is None:
|
|
232
257
|
# Note: In this case, warnings does nothing
|
|
233
258
|
warnings = set()
|
|
234
259
|
|
|
235
|
-
# A value that can never be a valid path so that we can tell if ANSIBLE_CONFIG was set later
|
|
236
|
-
# We can't use None because we could set path to None.
|
|
237
|
-
SENTINEL = object
|
|
238
|
-
|
|
239
260
|
potential_paths = []
|
|
240
261
|
|
|
262
|
+
# A value that can never be a valid path so that we can tell if ANSIBLE_CONFIG was set later
|
|
263
|
+
# We can't use None because we could set path to None.
|
|
241
264
|
# Environment setting
|
|
242
|
-
path_from_env = os.getenv("ANSIBLE_CONFIG",
|
|
243
|
-
if path_from_env is not
|
|
265
|
+
path_from_env = os.getenv("ANSIBLE_CONFIG", Sentinel)
|
|
266
|
+
if path_from_env is not Sentinel:
|
|
244
267
|
path_from_env = unfrackpath(path_from_env, follow=False)
|
|
245
268
|
if os.path.isdir(to_bytes(path_from_env)):
|
|
246
269
|
path_from_env = os.path.join(path_from_env, "ansible.cfg")
|
|
@@ -290,7 +313,7 @@ def find_ini_config_file(warnings=None):
|
|
|
290
313
|
|
|
291
314
|
|
|
292
315
|
def _add_base_defs_deprecations(base_defs):
|
|
293
|
-
|
|
316
|
+
"""Add deprecation source 'ansible.builtin' to deprecations in base.yml"""
|
|
294
317
|
def process(entry):
|
|
295
318
|
if 'deprecated' in entry:
|
|
296
319
|
entry['deprecated']['collection_name'] = 'ansible.builtin'
|
|
@@ -303,12 +326,15 @@ def _add_base_defs_deprecations(base_defs):
|
|
|
303
326
|
process(entry)
|
|
304
327
|
|
|
305
328
|
|
|
306
|
-
class ConfigManager
|
|
329
|
+
class ConfigManager:
|
|
307
330
|
|
|
308
331
|
DEPRECATED = [] # type: list[tuple[str, dict[str, str]]]
|
|
309
332
|
WARNINGS = set() # type: set[str]
|
|
310
333
|
|
|
334
|
+
_errors: list[tuple[str, Exception]]
|
|
335
|
+
|
|
311
336
|
def __init__(self, conf_file=None, defs_file=None):
|
|
337
|
+
self._get_ini_config_value = functools.cache(self._get_ini_config_value)
|
|
312
338
|
|
|
313
339
|
self._base_defs = {}
|
|
314
340
|
self._plugins = {}
|
|
@@ -328,6 +354,9 @@ class ConfigManager(object):
|
|
|
328
354
|
# initialize parser and read config
|
|
329
355
|
self._parse_config_file()
|
|
330
356
|
|
|
357
|
+
self._errors = []
|
|
358
|
+
"""Deferred errors that will be turned into warnings."""
|
|
359
|
+
|
|
331
360
|
# ensure we always have config def entry
|
|
332
361
|
self._base_defs['CONFIG_FILE'] = {'default': None, 'type': 'path'}
|
|
333
362
|
|
|
@@ -367,15 +396,16 @@ class ConfigManager(object):
|
|
|
367
396
|
defs = dict((k, server_config_def(server_key, k, req, value_type)) for k, req, value_type in GALAXY_SERVER_DEF)
|
|
368
397
|
self.initialize_plugin_configuration_definitions('galaxy_server', server_key, defs)
|
|
369
398
|
|
|
370
|
-
def template_default(self, value, variables):
|
|
371
|
-
if isinstance(value,
|
|
399
|
+
def template_default(self, value, variables, key_name: str = '<unknown>'):
|
|
400
|
+
if isinstance(value, str) and (value.startswith('{{') and value.endswith('}}')) and variables is not None:
|
|
372
401
|
# template default values if possible
|
|
373
402
|
# NOTE: cannot use is_template due to circular dep
|
|
374
403
|
try:
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
404
|
+
# FIXME: This really should be using an immutable sandboxed native environment, not just native environment
|
|
405
|
+
template = NativeEnvironment().from_string(value)
|
|
406
|
+
value = template.render(variables)
|
|
407
|
+
except Exception as ex:
|
|
408
|
+
self._errors.append((f'Failed to template default for config {key_name}.', ex))
|
|
379
409
|
return value
|
|
380
410
|
|
|
381
411
|
def _read_config_yaml_file(self, yml_file):
|
|
@@ -389,7 +419,7 @@ class ConfigManager(object):
|
|
|
389
419
|
"Missing base YAML definition file (bad install?): %s" % to_native(yml_file))
|
|
390
420
|
|
|
391
421
|
def _parse_config_file(self, cfile=None):
|
|
392
|
-
|
|
422
|
+
""" return flat configuration settings from file(s) """
|
|
393
423
|
# TODO: take list of files with merge/nomerge
|
|
394
424
|
|
|
395
425
|
if cfile is None:
|
|
@@ -416,7 +446,7 @@ class ConfigManager(object):
|
|
|
416
446
|
raise AnsibleOptionsError("Unsupported configuration file type: %s" % to_native(ftype))
|
|
417
447
|
|
|
418
448
|
def _find_yaml_config_files(self):
|
|
419
|
-
|
|
449
|
+
""" Load YAML Config Files in order, check merge flags, keep origin of settings"""
|
|
420
450
|
pass
|
|
421
451
|
|
|
422
452
|
def get_plugin_options(self, plugin_type, name, keys=None, variables=None, direct=None):
|
|
@@ -468,7 +498,7 @@ class ConfigManager(object):
|
|
|
468
498
|
return has
|
|
469
499
|
|
|
470
500
|
def get_configuration_definitions(self, plugin_type=None, name=None, ignore_private=False):
|
|
471
|
-
|
|
501
|
+
""" just list the possible settings, either base or for specific plugins or plugin """
|
|
472
502
|
|
|
473
503
|
ret = {}
|
|
474
504
|
if plugin_type is None:
|
|
@@ -478,14 +508,14 @@ class ConfigManager(object):
|
|
|
478
508
|
else:
|
|
479
509
|
ret = self._plugins.get(plugin_type, {}).get(name, {})
|
|
480
510
|
|
|
481
|
-
if ignore_private:
|
|
511
|
+
if ignore_private: # ignore 'test' config entries, they should not change runtime behaviors
|
|
482
512
|
for cdef in list(ret.keys()):
|
|
483
|
-
if cdef.startswith('
|
|
513
|
+
if cdef.startswith('_Z_'):
|
|
484
514
|
del ret[cdef]
|
|
485
515
|
return ret
|
|
486
516
|
|
|
487
517
|
def _loop_entries(self, container, entry_list):
|
|
488
|
-
|
|
518
|
+
""" repeat code for value entry assignment """
|
|
489
519
|
|
|
490
520
|
value = None
|
|
491
521
|
origin = None
|
|
@@ -497,10 +527,6 @@ class ConfigManager(object):
|
|
|
497
527
|
self.WARNINGS.add(u'value for config entry {0} contains invalid characters, ignoring...'.format(to_text(name)))
|
|
498
528
|
continue
|
|
499
529
|
if temp_value is not None: # only set if entry is defined in container
|
|
500
|
-
# inline vault variables should be converted to a text string
|
|
501
|
-
if isinstance(temp_value, AnsibleVaultEncryptedUnicode):
|
|
502
|
-
temp_value = to_text(temp_value, errors='surrogate_or_strict')
|
|
503
|
-
|
|
504
530
|
value = temp_value
|
|
505
531
|
origin = name
|
|
506
532
|
|
|
@@ -511,19 +537,23 @@ class ConfigManager(object):
|
|
|
511
537
|
return value, origin
|
|
512
538
|
|
|
513
539
|
def get_config_value(self, config, cfile=None, plugin_type=None, plugin_name=None, keys=None, variables=None, direct=None):
|
|
514
|
-
|
|
540
|
+
""" wrapper """
|
|
515
541
|
|
|
516
542
|
try:
|
|
517
543
|
value, _drop = self.get_config_value_and_origin(config, cfile=cfile, plugin_type=plugin_type, plugin_name=plugin_name,
|
|
518
544
|
keys=keys, variables=variables, direct=direct)
|
|
519
545
|
except AnsibleError:
|
|
520
546
|
raise
|
|
521
|
-
except Exception as
|
|
522
|
-
raise AnsibleError("Unhandled exception when retrieving
|
|
547
|
+
except Exception as ex:
|
|
548
|
+
raise AnsibleError(f"Unhandled exception when retrieving {config!r}.") from ex
|
|
523
549
|
return value
|
|
524
550
|
|
|
551
|
+
def get_config_default(self, config: str, plugin_type: str | None = None, plugin_name: str | None = None) -> t.Any:
|
|
552
|
+
"""Return the default value for the specified configuration."""
|
|
553
|
+
return self.get_configuration_definitions(plugin_type, plugin_name)[config]['default']
|
|
554
|
+
|
|
525
555
|
def get_config_value_and_origin(self, config, cfile=None, plugin_type=None, plugin_name=None, keys=None, variables=None, direct=None):
|
|
526
|
-
|
|
556
|
+
""" Given a config key figure out the actual value and report on the origin of the settings """
|
|
527
557
|
if cfile is None:
|
|
528
558
|
# use default config
|
|
529
559
|
cfile = self._config_file
|
|
@@ -588,6 +618,7 @@ class ConfigManager(object):
|
|
|
588
618
|
# env vars are next precedence
|
|
589
619
|
if value is None and defs[config].get('env'):
|
|
590
620
|
value, origin = self._loop_entries(os.environ, defs[config]['env'])
|
|
621
|
+
value = _tags.TrustedAsTemplate().tag(value)
|
|
591
622
|
origin = 'env: %s' % origin
|
|
592
623
|
|
|
593
624
|
# try config file entries next, if we have one
|
|
@@ -602,7 +633,7 @@ class ConfigManager(object):
|
|
|
602
633
|
for entry in defs[config][ftype]:
|
|
603
634
|
# load from config
|
|
604
635
|
if ftype == 'ini':
|
|
605
|
-
temp_value =
|
|
636
|
+
temp_value = self._get_ini_config_value(cfile, entry.get('section', 'defaults'), entry['key'])
|
|
606
637
|
elif ftype == 'yaml':
|
|
607
638
|
raise AnsibleError('YAML configuration type has not been implemented yet')
|
|
608
639
|
else:
|
|
@@ -626,22 +657,21 @@ class ConfigManager(object):
|
|
|
626
657
|
if value is None:
|
|
627
658
|
if defs[config].get('required', False):
|
|
628
659
|
if not plugin_type or config not in INTERNAL_DEFS.get(plugin_type, {}):
|
|
629
|
-
raise AnsibleRequiredOptionError("
|
|
630
|
-
to_native(_get_entry(plugin_type, plugin_name, config)))
|
|
660
|
+
raise AnsibleRequiredOptionError(f"Required config {_get_config_label(plugin_type, plugin_name, config)} not provided.")
|
|
631
661
|
else:
|
|
632
662
|
origin = 'default'
|
|
633
|
-
value = self.template_default(defs[config].get('default'), variables)
|
|
663
|
+
value = self.template_default(defs[config].get('default'), variables, key_name=_get_config_label(plugin_type, plugin_name, config))
|
|
664
|
+
|
|
634
665
|
try:
|
|
635
666
|
# ensure correct type, can raise exceptions on mismatched types
|
|
636
667
|
value = ensure_type(value, defs[config].get('type'), origin=origin, origin_ftype=origin_ftype)
|
|
637
|
-
except ValueError as
|
|
668
|
+
except ValueError as ex:
|
|
638
669
|
if origin.startswith('env:') and value == '':
|
|
639
670
|
# this is empty env var for non string so we can set to default
|
|
640
671
|
origin = 'default'
|
|
641
672
|
value = ensure_type(defs[config].get('default'), defs[config].get('type'), origin=origin, origin_ftype=origin_ftype)
|
|
642
673
|
else:
|
|
643
|
-
raise AnsibleOptionsError('
|
|
644
|
-
(to_native(_get_entry(plugin_type, plugin_name, config)).strip(), origin, to_native(e)))
|
|
674
|
+
raise AnsibleOptionsError(f'Config {_get_config_label(plugin_type, plugin_name, config)} from {origin!r} has an invalid value.') from ex
|
|
645
675
|
|
|
646
676
|
# deal with restricted values
|
|
647
677
|
if value is not None and 'choices' in defs[config] and defs[config]['choices'] is not None:
|
|
@@ -657,21 +687,24 @@ class ConfigManager(object):
|
|
|
657
687
|
|
|
658
688
|
if isinstance(defs[config]['choices'], Mapping):
|
|
659
689
|
valid = ', '.join([to_text(k) for k in defs[config]['choices'].keys()])
|
|
660
|
-
elif isinstance(defs[config]['choices'],
|
|
690
|
+
elif isinstance(defs[config]['choices'], str):
|
|
661
691
|
valid = defs[config]['choices']
|
|
662
692
|
elif isinstance(defs[config]['choices'], Sequence):
|
|
663
693
|
valid = ', '.join([to_text(c) for c in defs[config]['choices']])
|
|
664
694
|
else:
|
|
665
695
|
valid = defs[config]['choices']
|
|
666
696
|
|
|
667
|
-
raise AnsibleOptionsError('Invalid value
|
|
668
|
-
|
|
697
|
+
raise AnsibleOptionsError(f'Invalid value {value!r} for config {_get_config_label(plugin_type, plugin_name, config)}.',
|
|
698
|
+
help_text=f'Valid values are: {valid}')
|
|
669
699
|
|
|
670
700
|
# deal with deprecation of the setting
|
|
671
701
|
if 'deprecated' in defs[config] and origin != 'default':
|
|
672
702
|
self.DEPRECATED.append((config, defs[config].get('deprecated')))
|
|
673
703
|
else:
|
|
674
|
-
raise
|
|
704
|
+
raise AnsibleUndefinedConfigEntry(f'No config definition exists for {_get_config_label(plugin_type, plugin_name, config)}.')
|
|
705
|
+
|
|
706
|
+
if not _tags.Origin.is_tagged_on(value):
|
|
707
|
+
value = _tags.Origin(description=f'<Config {origin}>').tag(value)
|
|
675
708
|
|
|
676
709
|
return value, origin
|
|
677
710
|
|
|
@@ -682,13 +715,41 @@ class ConfigManager(object):
|
|
|
682
715
|
|
|
683
716
|
self._plugins[plugin_type][name] = defs
|
|
684
717
|
|
|
718
|
+
def _get_ini_config_value(self, config_file: str, section: str, option: str) -> t.Any:
|
|
719
|
+
"""
|
|
720
|
+
Fetch `option` from the specified `section`.
|
|
721
|
+
Returns `None` if the specified `section` or `option` are not present.
|
|
722
|
+
Origin and TrustedAsTemplate tags are applied to returned values.
|
|
723
|
+
|
|
724
|
+
CAUTION: Although INI sourced configuration values are trusted for templating, that does not automatically mean they will be templated.
|
|
725
|
+
It is up to the code consuming configuration values to apply templating if required.
|
|
726
|
+
"""
|
|
727
|
+
parser = self._parsers[config_file]
|
|
728
|
+
value = parser.get(section, option, raw=True, fallback=None)
|
|
729
|
+
|
|
730
|
+
if value is not None:
|
|
731
|
+
value = self._apply_tags(value, section, option)
|
|
732
|
+
|
|
733
|
+
return value
|
|
734
|
+
|
|
735
|
+
def _apply_tags(self, value: str, section: str, option: str) -> t.Any:
|
|
736
|
+
"""Apply origin and trust to the given `value` sourced from the stated `section` and `option`."""
|
|
737
|
+
description = f'section {section!r} option {option!r}'
|
|
738
|
+
origin = _tags.Origin(path=self._config_file, description=description)
|
|
739
|
+
tags = [origin, _tags.TrustedAsTemplate()]
|
|
740
|
+
value = AnsibleTagHelper.tag(value, tags)
|
|
741
|
+
|
|
742
|
+
return value
|
|
743
|
+
|
|
685
744
|
@staticmethod
|
|
686
|
-
def get_deprecated_msg_from_config(dep_docs, include_removal=False):
|
|
745
|
+
def get_deprecated_msg_from_config(dep_docs, include_removal=False, collection_name=None):
|
|
687
746
|
|
|
688
747
|
removal = ''
|
|
689
748
|
if include_removal:
|
|
690
749
|
if 'removed_at_date' in dep_docs:
|
|
691
750
|
removal = f"Will be removed in a release after {dep_docs['removed_at_date']}\n\t"
|
|
751
|
+
elif collection_name:
|
|
752
|
+
removal = f"Will be removed in: {collection_name} {dep_docs['removed_in']}\n\t"
|
|
692
753
|
else:
|
|
693
754
|
removal = f"Will be removed in: Ansible {dep_docs['removed_in']}\n\t"
|
|
694
755
|
|