ansible-core 2.18.7__py3-none-any.whl → 2.19.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ansible-core might be problematic. Click here for more details.
- ansible/_internal/__init__.py +53 -0
- ansible/_internal/_ansiballz/__init__.py +0 -0
- ansible/_internal/_ansiballz/_builder.py +101 -0
- ansible/_internal/_ansiballz/_wrapper.py +262 -0
- ansible/_internal/_collection_proxy.py +47 -0
- ansible/_internal/_datatag/__init__.py +0 -0
- ansible/_internal/_datatag/_tags.py +130 -0
- ansible/_internal/_datatag/_utils.py +19 -0
- ansible/_internal/_datatag/_wrappers.py +33 -0
- ansible/_internal/_errors/__init__.py +0 -0
- ansible/_internal/_errors/_alarm_timeout.py +66 -0
- ansible/_internal/_errors/_captured.py +123 -0
- ansible/_internal/_errors/_error_factory.py +89 -0
- ansible/_internal/_errors/_error_utils.py +240 -0
- ansible/_internal/_errors/_handler.py +91 -0
- ansible/_internal/_errors/_task_timeout.py +28 -0
- ansible/_internal/_event_formatting.py +127 -0
- ansible/_internal/_json/__init__.py +214 -0
- ansible/_internal/_json/_legacy_encoder.py +34 -0
- ansible/_internal/_json/_profiles/__init__.py +0 -0
- ansible/_internal/_json/_profiles/_cache_persistence.py +57 -0
- ansible/_internal/_json/_profiles/_inventory_legacy.py +40 -0
- ansible/_internal/_json/_profiles/_legacy.py +189 -0
- ansible/_internal/_locking.py +21 -0
- ansible/_internal/_plugins/__init__.py +0 -0
- ansible/_internal/_plugins/_cache.py +57 -0
- ansible/_internal/_ssh/__init__.py +0 -0
- ansible/_internal/_ssh/_agent_launch.py +91 -0
- ansible/_internal/_ssh/_ssh_agent.py +619 -0
- ansible/_internal/_task.py +78 -0
- ansible/_internal/_templating/__init__.py +12 -0
- ansible/_internal/_templating/_access.py +86 -0
- ansible/_internal/_templating/_chain_templar.py +63 -0
- ansible/_internal/_templating/_datatag.py +95 -0
- ansible/_internal/_templating/_engine.py +592 -0
- ansible/_internal/_templating/_errors.py +28 -0
- ansible/_internal/_templating/_jinja_bits.py +1106 -0
- ansible/_internal/_templating/_jinja_common.py +323 -0
- ansible/_internal/_templating/_jinja_patches.py +44 -0
- ansible/_internal/_templating/_jinja_plugins.py +375 -0
- ansible/_internal/_templating/_lazy_containers.py +633 -0
- ansible/_internal/_templating/_marker_behaviors.py +103 -0
- ansible/_internal/_templating/_template_vars.py +72 -0
- ansible/_internal/_templating/_transform.py +70 -0
- ansible/_internal/_templating/_utils.py +108 -0
- ansible/_internal/_testing.py +26 -0
- ansible/_internal/_wrapt.py +1052 -0
- ansible/_internal/_yaml/__init__.py +0 -0
- ansible/_internal/_yaml/_constructor.py +240 -0
- ansible/_internal/_yaml/_dumper.py +70 -0
- ansible/_internal/_yaml/_errors.py +166 -0
- ansible/_internal/_yaml/_loader.py +66 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/README.md +11 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/action/debug.py +36 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/apply_trust.py +19 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/dump_object.py +27 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/finalize.py +16 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/origin.py +18 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/python_literal_eval.py +24 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/python_literal_eval.yml +33 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/tag_names.py +16 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/true_type.py +17 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/unmask.py +49 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/lookup/config.py +21 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/lookup/config.yml +2 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged.py +15 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged.yml +19 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged_with.py +18 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged_with.yml +19 -0
- ansible/cli/__init__.py +93 -104
- ansible/cli/_ssh_askpass.py +54 -0
- ansible/cli/adhoc.py +20 -10
- ansible/cli/arguments/option_helpers.py +163 -10
- ansible/cli/config.py +43 -68
- ansible/cli/console.py +13 -11
- ansible/cli/doc.py +134 -77
- ansible/cli/galaxy.py +27 -20
- ansible/cli/inventory.py +28 -28
- ansible/cli/playbook.py +4 -12
- ansible/cli/pull.py +6 -3
- ansible/cli/scripts/ansible_connection_cli_stub.py +7 -7
- ansible/cli/vault.py +12 -11
- ansible/compat/__init__.py +2 -2
- ansible/compat/importlib_resources.py +9 -12
- ansible/config/base.yml +218 -133
- ansible/config/manager.py +220 -159
- ansible/constants.py +2 -65
- ansible/errors/__init__.py +350 -256
- ansible/executor/interpreter_discovery.py +28 -149
- ansible/executor/module_common.py +480 -514
- ansible/executor/play_iterator.py +22 -27
- ansible/executor/playbook_executor.py +11 -11
- ansible/executor/powershell/async_watchdog.ps1 +97 -102
- ansible/executor/powershell/async_wrapper.ps1 +204 -153
- ansible/executor/powershell/become_wrapper.ps1 +107 -144
- ansible/executor/powershell/bootstrap_wrapper.ps1 +46 -9
- ansible/executor/powershell/coverage_wrapper.ps1 +91 -135
- ansible/executor/powershell/exec_wrapper.ps1 +675 -196
- ansible/executor/powershell/module_manifest.py +469 -265
- ansible/executor/powershell/module_wrapper.ps1 +195 -186
- ansible/executor/powershell/powershell_expand_user.ps1 +20 -0
- ansible/executor/powershell/powershell_mkdtemp.ps1 +17 -0
- ansible/executor/powershell/psrp_fetch_file.ps1 +41 -0
- ansible/executor/powershell/psrp_put_file.ps1 +122 -0
- ansible/executor/powershell/winrm_fetch_file.ps1 +46 -0
- ansible/executor/powershell/winrm_put_file.ps1 +36 -0
- ansible/executor/process/worker.py +139 -149
- ansible/executor/stats.py +5 -5
- ansible/executor/task_executor.py +270 -297
- ansible/executor/task_queue_manager.py +135 -137
- ansible/executor/task_result.py +182 -79
- ansible/galaxy/__init__.py +2 -2
- ansible/galaxy/api.py +26 -25
- ansible/galaxy/collection/__init__.py +6 -14
- ansible/galaxy/collection/concrete_artifact_manager.py +12 -21
- ansible/galaxy/dependency_resolution/dataclasses.py +14 -4
- ansible/galaxy/dependency_resolution/providers.py +4 -4
- ansible/galaxy/dependency_resolution/reporters.py +81 -0
- ansible/galaxy/role.py +6 -10
- ansible/galaxy/token.py +28 -21
- ansible/inventory/data.py +47 -57
- ansible/inventory/group.py +50 -73
- ansible/inventory/helpers.py +9 -0
- ansible/inventory/host.py +37 -54
- ansible/inventory/manager.py +79 -34
- ansible/keyword_desc.yml +1 -1
- ansible/module_utils/_internal/__init__.py +55 -0
- ansible/module_utils/_internal/_ambient_context.py +58 -0
- ansible/module_utils/_internal/_ansiballz/__init__.py +0 -0
- ansible/module_utils/_internal/_ansiballz/_extensions/__init__.py +0 -0
- ansible/module_utils/_internal/_ansiballz/_extensions/_coverage.py +45 -0
- ansible/module_utils/_internal/_ansiballz/_extensions/_pydevd.py +62 -0
- ansible/module_utils/_internal/_ansiballz/_loader.py +81 -0
- ansible/module_utils/_internal/_ansiballz/_respawn.py +32 -0
- ansible/module_utils/_internal/_ansiballz/_respawn_wrapper.py +23 -0
- ansible/module_utils/_internal/_concurrent/_daemon_threading.py +1 -0
- ansible/module_utils/_internal/_dataclass_validation.py +217 -0
- ansible/module_utils/_internal/_datatag/__init__.py +961 -0
- ansible/module_utils/_internal/_datatag/_tags.py +16 -0
- ansible/module_utils/_internal/_debugging.py +31 -0
- ansible/module_utils/_internal/_deprecator.py +157 -0
- ansible/module_utils/_internal/_errors.py +101 -0
- ansible/module_utils/_internal/_event_utils.py +61 -0
- ansible/module_utils/_internal/_json/__init__.py +63 -0
- ansible/module_utils/_internal/_json/_legacy_encoder.py +26 -0
- ansible/module_utils/_internal/_json/_profiles/__init__.py +428 -0
- ansible/module_utils/_internal/_json/_profiles/_fallback_to_str.py +73 -0
- ansible/module_utils/_internal/_json/_profiles/_module_legacy_c2m.py +33 -0
- ansible/module_utils/_internal/_json/_profiles/_module_legacy_m2c.py +37 -0
- ansible/module_utils/_internal/_json/_profiles/_module_modern_c2m.py +35 -0
- ansible/module_utils/_internal/_json/_profiles/_module_modern_m2c.py +33 -0
- ansible/module_utils/_internal/_json/_profiles/_tagless.py +52 -0
- ansible/module_utils/_internal/_messages.py +130 -0
- ansible/module_utils/_internal/_patches/__init__.py +66 -0
- ansible/module_utils/_internal/_patches/_dataclass_annotation_patch.py +53 -0
- ansible/module_utils/_internal/_patches/_socket_patch.py +34 -0
- ansible/module_utils/_internal/_patches/_sys_intern_patch.py +34 -0
- ansible/module_utils/_internal/_plugin_info.py +38 -0
- ansible/module_utils/_internal/_stack.py +22 -0
- ansible/module_utils/_internal/_testing.py +0 -0
- ansible/module_utils/_internal/_text_utils.py +6 -0
- ansible/module_utils/_internal/_traceback.py +92 -0
- ansible/module_utils/_internal/_validation.py +14 -0
- ansible/module_utils/ansible_release.py +2 -2
- ansible/module_utils/api.py +1 -2
- ansible/module_utils/basic.py +303 -202
- ansible/module_utils/common/_utils.py +24 -28
- ansible/module_utils/common/arg_spec.py +8 -3
- ansible/module_utils/common/collections.py +7 -2
- ansible/module_utils/common/dict_transformations.py +2 -2
- ansible/module_utils/common/file.py +2 -2
- ansible/module_utils/common/json.py +90 -84
- ansible/module_utils/common/locale.py +2 -2
- ansible/module_utils/common/parameters.py +27 -24
- ansible/module_utils/common/process.py +2 -3
- ansible/module_utils/common/respawn.py +11 -33
- ansible/module_utils/common/sentinel.py +66 -0
- ansible/module_utils/common/sys_info.py +8 -8
- ansible/module_utils/common/text/converters.py +16 -37
- ansible/module_utils/common/validation.py +35 -24
- ansible/module_utils/common/warnings.py +143 -25
- ansible/module_utils/common/yaml.py +29 -3
- ansible/module_utils/compat/datetime.py +33 -21
- ansible/module_utils/compat/paramiko.py +21 -10
- ansible/module_utils/compat/typing.py +6 -5
- ansible/module_utils/connection.py +10 -13
- ansible/module_utils/csharp/Ansible.Basic.cs +15 -12
- ansible/module_utils/csharp/Ansible.Become.cs +1 -0
- ansible/module_utils/csharp/Ansible.Privilege.cs +2 -2
- ansible/module_utils/csharp/Ansible._Async.cs +517 -0
- ansible/module_utils/datatag.py +49 -0
- ansible/module_utils/distro/__init__.py +2 -2
- ansible/module_utils/facts/ansible_collector.py +4 -5
- ansible/module_utils/facts/collector.py +13 -14
- ansible/module_utils/facts/compat.py +4 -4
- ansible/module_utils/facts/default_collectors.py +1 -1
- ansible/module_utils/facts/hardware/aix.py +34 -0
- ansible/module_utils/facts/hardware/base.py +2 -2
- ansible/module_utils/facts/hardware/darwin.py +1 -3
- ansible/module_utils/facts/hardware/freebsd.py +2 -2
- ansible/module_utils/facts/hardware/linux.py +5 -5
- ansible/module_utils/facts/namespace.py +1 -1
- ansible/module_utils/facts/network/base.py +1 -1
- ansible/module_utils/facts/network/fc_wwn.py +1 -2
- ansible/module_utils/facts/network/iscsi.py +1 -2
- ansible/module_utils/facts/network/nvme.py +1 -2
- ansible/module_utils/facts/other/facter.py +2 -3
- ansible/module_utils/facts/other/ohai.py +2 -3
- ansible/module_utils/facts/sysctl.py +4 -6
- ansible/module_utils/facts/system/apparmor.py +1 -2
- ansible/module_utils/facts/system/caps.py +3 -3
- ansible/module_utils/facts/system/chroot.py +1 -2
- ansible/module_utils/facts/system/cmdline.py +1 -2
- ansible/module_utils/facts/system/date_time.py +5 -3
- ansible/module_utils/facts/system/distribution.py +27 -13
- ansible/module_utils/facts/system/dns.py +1 -1
- ansible/module_utils/facts/system/env.py +1 -2
- ansible/module_utils/facts/system/fips.py +7 -20
- ansible/module_utils/facts/system/loadavg.py +1 -2
- ansible/module_utils/facts/system/local.py +2 -3
- ansible/module_utils/facts/system/lsb.py +1 -2
- ansible/module_utils/facts/system/pkg_mgr.py +1 -2
- ansible/module_utils/facts/system/platform.py +1 -2
- ansible/module_utils/facts/system/python.py +1 -2
- ansible/module_utils/facts/system/selinux.py +1 -1
- ansible/module_utils/facts/system/service_mgr.py +1 -2
- ansible/module_utils/facts/system/ssh_pub_keys.py +1 -1
- ansible/module_utils/facts/system/systemd.py +1 -1
- ansible/module_utils/facts/system/user.py +1 -2
- ansible/module_utils/facts/utils.py +3 -3
- ansible/module_utils/facts/virtual/base.py +1 -1
- ansible/module_utils/facts/virtual/linux.py +3 -3
- ansible/module_utils/facts/virtual/sunos.py +3 -15
- ansible/module_utils/facts/virtual/sysctl.py +3 -16
- ansible/module_utils/json_utils.py +2 -2
- ansible/module_utils/parsing/convert_bool.py +7 -1
- ansible/module_utils/powershell/Ansible.ModuleUtils.AddType.psm1 +1 -1
- ansible/module_utils/powershell/Ansible.ModuleUtils.CamelConversion.psm1 +1 -1
- ansible/module_utils/powershell/Ansible.ModuleUtils.CommandUtil.psm1 +1 -1
- ansible/module_utils/powershell/Ansible.ModuleUtils.WebRequest.psm1 +1 -1
- ansible/module_utils/service.py +21 -31
- ansible/module_utils/splitter.py +7 -7
- ansible/module_utils/testing.py +31 -0
- ansible/module_utils/urls.py +64 -35
- ansible/modules/add_host.py +4 -4
- ansible/modules/apt.py +69 -49
- ansible/modules/apt_key.py +19 -12
- ansible/modules/apt_repository.py +32 -51
- ansible/modules/assemble.py +16 -14
- ansible/modules/assert.py +4 -4
- ansible/modules/async_status.py +24 -24
- ansible/modules/async_wrapper.py +20 -25
- ansible/modules/blockinfile.py +6 -7
- ansible/modules/command.py +13 -20
- ansible/modules/copy.py +60 -147
- ansible/modules/cron.py +24 -21
- ansible/modules/deb822_repository.py +8 -9
- ansible/modules/debconf.py +5 -5
- ansible/modules/debug.py +4 -4
- ansible/modules/dnf.py +8 -8
- ansible/modules/dnf5.py +39 -13
- ansible/modules/dpkg_selections.py +4 -4
- ansible/modules/expect.py +13 -15
- ansible/modules/fail.py +4 -4
- ansible/modules/fetch.py +4 -4
- ansible/modules/file.py +184 -144
- ansible/modules/find.py +22 -20
- ansible/modules/gather_facts.py +3 -3
- ansible/modules/get_url.py +77 -54
- ansible/modules/getent.py +7 -9
- ansible/modules/git.py +38 -38
- ansible/modules/group.py +6 -6
- ansible/modules/group_by.py +4 -4
- ansible/modules/hostname.py +15 -32
- ansible/modules/import_playbook.py +6 -6
- ansible/modules/import_role.py +6 -6
- ansible/modules/import_tasks.py +6 -6
- ansible/modules/include_role.py +6 -6
- ansible/modules/include_tasks.py +6 -6
- ansible/modules/include_vars.py +6 -6
- ansible/modules/iptables.py +86 -73
- ansible/modules/known_hosts.py +22 -24
- ansible/modules/lineinfile.py +5 -5
- ansible/modules/meta.py +4 -4
- ansible/modules/mount_facts.py +2 -2
- ansible/modules/package.py +10 -4
- ansible/modules/package_facts.py +22 -10
- ansible/modules/pause.py +6 -6
- ansible/modules/ping.py +6 -6
- ansible/modules/pip.py +21 -26
- ansible/modules/raw.py +6 -6
- ansible/modules/reboot.py +6 -6
- ansible/modules/replace.py +10 -14
- ansible/modules/rpm_key.py +7 -8
- ansible/modules/script.py +4 -4
- ansible/modules/service.py +10 -17
- ansible/modules/service_facts.py +87 -10
- ansible/modules/set_fact.py +5 -5
- ansible/modules/set_stats.py +4 -4
- ansible/modules/setup.py +2 -2
- ansible/modules/shell.py +6 -6
- ansible/modules/slurp.py +16 -19
- ansible/modules/stat.py +15 -31
- ansible/modules/subversion.py +15 -15
- ansible/modules/systemd.py +7 -7
- ansible/modules/systemd_service.py +7 -7
- ansible/modules/sysvinit.py +9 -9
- ansible/modules/tempfile.py +5 -6
- ansible/modules/template.py +6 -6
- ansible/modules/unarchive.py +38 -17
- ansible/modules/uri.py +33 -26
- ansible/modules/user.py +45 -32
- ansible/modules/validate_argument_spec.py +10 -7
- ansible/modules/wait_for.py +70 -60
- ansible/modules/wait_for_connection.py +6 -6
- ansible/modules/yum_repository.py +10 -9
- ansible/parsing/ajson.py +17 -37
- ansible/parsing/dataloader.py +99 -54
- ansible/parsing/mod_args.py +62 -60
- ansible/parsing/plugin_docs.py +21 -86
- ansible/parsing/quoting.py +1 -1
- ansible/parsing/splitter.py +27 -12
- ansible/parsing/utils/addresses.py +24 -24
- ansible/parsing/utils/jsonify.py +5 -1
- ansible/parsing/utils/yaml.py +32 -61
- ansible/parsing/vault/__init__.py +327 -99
- ansible/parsing/yaml/__init__.py +0 -18
- ansible/parsing/yaml/dumper.py +6 -120
- ansible/parsing/yaml/loader.py +6 -39
- ansible/parsing/yaml/objects.py +43 -335
- ansible/playbook/__init__.py +1 -1
- ansible/playbook/attribute.py +8 -3
- ansible/playbook/base.py +187 -134
- ansible/playbook/block.py +26 -24
- ansible/playbook/collectionsearch.py +1 -15
- ansible/playbook/conditional.py +3 -77
- ansible/playbook/handler.py +8 -2
- ansible/playbook/helpers.py +41 -53
- ansible/playbook/included_file.py +32 -26
- ansible/playbook/loop_control.py +2 -2
- ansible/playbook/play.py +85 -44
- ansible/playbook/play_context.py +14 -17
- ansible/playbook/playbook_include.py +27 -62
- ansible/playbook/role/__init__.py +64 -49
- ansible/playbook/role/definition.py +15 -17
- ansible/playbook/role/include.py +2 -4
- ansible/playbook/role/metadata.py +10 -11
- ansible/playbook/role_include.py +3 -3
- ansible/playbook/taggable.py +28 -12
- ansible/playbook/task.py +192 -121
- ansible/playbook/task_include.py +5 -5
- ansible/plugins/__init__.py +58 -26
- ansible/plugins/action/__init__.py +188 -186
- ansible/plugins/action/add_host.py +2 -2
- ansible/plugins/action/assemble.py +11 -18
- ansible/plugins/action/assert.py +55 -67
- ansible/plugins/action/async_status.py +7 -2
- ansible/plugins/action/copy.py +14 -17
- ansible/plugins/action/debug.py +37 -31
- ansible/plugins/action/dnf.py +3 -4
- ansible/plugins/action/fail.py +1 -1
- ansible/plugins/action/fetch.py +7 -8
- ansible/plugins/action/gather_facts.py +13 -14
- ansible/plugins/action/group_by.py +1 -1
- ansible/plugins/action/include_vars.py +10 -11
- ansible/plugins/action/package.py +8 -14
- ansible/plugins/action/pause.py +2 -2
- ansible/plugins/action/script.py +27 -38
- ansible/plugins/action/service.py +9 -18
- ansible/plugins/action/set_fact.py +3 -12
- ansible/plugins/action/set_stats.py +3 -8
- ansible/plugins/action/template.py +47 -67
- ansible/plugins/action/unarchive.py +6 -16
- ansible/plugins/action/uri.py +9 -20
- ansible/plugins/action/validate_argument_spec.py +5 -5
- ansible/plugins/action/wait_for_connection.py +1 -1
- ansible/plugins/become/__init__.py +31 -8
- ansible/plugins/become/runas.py +71 -0
- ansible/plugins/become/su.py +13 -8
- ansible/plugins/become/sudo.py +19 -0
- ansible/plugins/cache/__init__.py +52 -63
- ansible/plugins/cache/base.py +8 -0
- ansible/plugins/cache/jsonfile.py +10 -16
- ansible/plugins/cache/memory.py +6 -12
- ansible/plugins/callback/__init__.py +294 -201
- ansible/plugins/callback/default.py +99 -95
- ansible/plugins/callback/junit.py +44 -43
- ansible/plugins/callback/minimal.py +28 -25
- ansible/plugins/callback/oneline.py +34 -21
- ansible/plugins/callback/tree.py +27 -16
- ansible/plugins/connection/__init__.py +47 -34
- ansible/plugins/connection/local.py +156 -60
- ansible/plugins/connection/paramiko_ssh.py +34 -24
- ansible/plugins/connection/psrp.py +76 -165
- ansible/plugins/connection/ssh.py +326 -86
- ansible/plugins/connection/winrm.py +62 -141
- ansible/plugins/doc_fragments/action_common_attributes.py +14 -14
- ansible/plugins/doc_fragments/action_core.py +6 -6
- ansible/plugins/doc_fragments/backup.py +2 -2
- ansible/plugins/doc_fragments/checksum_common.py +27 -0
- ansible/plugins/doc_fragments/constructed.py +8 -4
- ansible/plugins/doc_fragments/decrypt.py +2 -2
- ansible/plugins/doc_fragments/default_callback.py +2 -2
- ansible/plugins/doc_fragments/files.py +2 -2
- ansible/plugins/doc_fragments/inventory_cache.py +2 -2
- ansible/plugins/doc_fragments/result_format_callback.py +2 -2
- ansible/plugins/doc_fragments/return_common.py +2 -2
- ansible/plugins/doc_fragments/template_common.py +4 -4
- ansible/plugins/doc_fragments/url.py +17 -1
- ansible/plugins/doc_fragments/url_windows.py +2 -2
- ansible/plugins/doc_fragments/validate.py +2 -2
- ansible/plugins/doc_fragments/vars_plugin_staging.py +2 -2
- ansible/plugins/filter/__init__.py +6 -2
- ansible/plugins/filter/b64decode.yml +22 -0
- ansible/plugins/filter/b64encode.yml +22 -0
- ansible/plugins/filter/bool.yml +11 -4
- ansible/plugins/filter/core.py +245 -120
- ansible/plugins/filter/encryption.py +42 -34
- ansible/plugins/filter/flatten.yml +3 -2
- ansible/plugins/filter/human_to_bytes.yml +1 -1
- ansible/plugins/filter/mathstuff.py +30 -37
- ansible/plugins/filter/password_hash.yml +8 -0
- ansible/plugins/filter/pow.yml +1 -1
- ansible/plugins/filter/regex_search.yml +1 -4
- ansible/plugins/filter/root.yml +1 -1
- ansible/plugins/filter/split.yml +1 -1
- ansible/plugins/filter/strftime.yml +3 -3
- ansible/plugins/filter/to_nice_yaml.yml +0 -4
- ansible/plugins/filter/to_uuid.yml +1 -1
- ansible/plugins/filter/to_yaml.yml +0 -4
- ansible/plugins/filter/unvault.yml +1 -1
- ansible/plugins/filter/urls.py +1 -1
- ansible/plugins/filter/urlsplit.py +8 -9
- ansible/plugins/filter/vault.yml +14 -9
- ansible/plugins/filter/win_basename.yml +6 -1
- ansible/plugins/filter/win_dirname.yml +5 -0
- ansible/plugins/inventory/__init__.py +107 -86
- ansible/plugins/inventory/advanced_host_list.py +7 -5
- ansible/plugins/inventory/auto.py +11 -4
- ansible/plugins/inventory/constructed.py +21 -24
- ansible/plugins/inventory/generator.py +16 -11
- ansible/plugins/inventory/host_list.py +7 -5
- ansible/plugins/inventory/ini.py +78 -44
- ansible/plugins/inventory/script.py +190 -120
- ansible/plugins/inventory/toml.py +16 -126
- ansible/plugins/inventory/yaml.py +10 -8
- ansible/plugins/list.py +72 -19
- ansible/plugins/loader.py +383 -198
- ansible/plugins/lookup/__init__.py +21 -4
- ansible/plugins/lookup/config.py +21 -35
- ansible/plugins/lookup/csvfile.py +19 -73
- ansible/plugins/lookup/dict.py +1 -6
- ansible/plugins/lookup/env.py +12 -9
- ansible/plugins/lookup/file.py +5 -8
- ansible/plugins/lookup/first_found.py +87 -55
- ansible/plugins/lookup/indexed_items.py +1 -10
- ansible/plugins/lookup/ini.py +14 -13
- ansible/plugins/lookup/items.py +1 -1
- ansible/plugins/lookup/lines.py +8 -1
- ansible/plugins/lookup/list.py +1 -1
- ansible/plugins/lookup/nested.py +2 -18
- ansible/plugins/lookup/password.py +5 -5
- ansible/plugins/lookup/pipe.py +5 -7
- ansible/plugins/lookup/sequence.py +18 -8
- ansible/plugins/lookup/subelements.py +1 -4
- ansible/plugins/lookup/template.py +47 -36
- ansible/plugins/lookup/together.py +0 -12
- ansible/plugins/lookup/unvault.py +1 -5
- ansible/plugins/lookup/url.py +4 -10
- ansible/plugins/lookup/vars.py +16 -24
- ansible/plugins/shell/__init__.py +58 -4
- ansible/plugins/shell/cmd.py +2 -2
- ansible/plugins/shell/powershell.py +106 -31
- ansible/plugins/shell/sh.py +13 -7
- ansible/plugins/strategy/__init__.py +168 -193
- ansible/plugins/strategy/debug.py +2 -2
- ansible/plugins/strategy/free.py +16 -31
- ansible/plugins/strategy/host_pinned.py +2 -2
- ansible/plugins/strategy/linear.py +41 -41
- ansible/plugins/terminal/__init__.py +4 -4
- ansible/plugins/test/__init__.py +7 -2
- ansible/plugins/test/core.py +75 -35
- ansible/plugins/test/files.py +1 -1
- ansible/plugins/test/finished.yml +1 -1
- ansible/plugins/test/mathstuff.py +3 -3
- ansible/plugins/test/uri.py +5 -8
- ansible/plugins/vars/host_group_vars.py +7 -14
- ansible/release.py +2 -2
- ansible/template/__init__.py +353 -943
- ansible/utils/__init__.py +0 -18
- ansible/utils/collection_loader/__init__.py +54 -5
- ansible/utils/collection_loader/_collection_config.py +5 -6
- ansible/utils/collection_loader/_collection_finder.py +82 -96
- ansible/utils/collection_loader/_collection_meta.py +15 -8
- ansible/utils/display.py +485 -73
- ansible/utils/encrypt.py +27 -19
- ansible/utils/fqcn.py +2 -2
- ansible/utils/galaxy.py +2 -2
- ansible/utils/hashing.py +8 -10
- ansible/utils/helpers.py +2 -2
- ansible/utils/listify.py +10 -8
- ansible/utils/lock.py +2 -2
- ansible/utils/path.py +10 -12
- ansible/utils/plugin_docs.py +16 -14
- ansible/utils/py3compat.py +2 -7
- ansible/utils/sentinel.py +4 -62
- ansible/utils/singleton.py +2 -0
- ansible/utils/ssh_functions.py +6 -2
- ansible/utils/unsafe_proxy.py +23 -332
- ansible/utils/vars.py +55 -8
- ansible/utils/version.py +2 -2
- ansible/vars/clean.py +5 -5
- ansible/vars/hostvars.py +60 -90
- ansible/vars/manager.py +220 -285
- ansible/vars/plugins.py +4 -4
- ansible/vars/reserved.py +13 -12
- {ansible_core-2.18.7.dist-info → ansible_core-2.19.0.dist-info}/METADATA +4 -3
- ansible_core-2.19.0.dist-info/RECORD +1097 -0
- ansible_core-2.19.0.dist-info/licenses/licenses/BSD-3-Clause.txt +28 -0
- ansible_test/_data/completion/docker.txt +7 -7
- ansible_test/_data/completion/remote.txt +6 -6
- ansible_test/_data/completion/windows.txt +1 -0
- ansible_test/_data/requirements/ansible.txt +2 -2
- ansible_test/_data/requirements/sanity.ansible-doc.txt +3 -3
- ansible_test/_data/requirements/sanity.changelog.txt +2 -2
- ansible_test/_data/requirements/sanity.import.plugin.txt +2 -2
- ansible_test/_data/requirements/sanity.pep8.txt +1 -1
- ansible_test/_data/requirements/sanity.pylint.txt +5 -5
- ansible_test/_data/requirements/sanity.validate-modules.txt +2 -2
- ansible_test/_data/requirements/sanity.yamllint.txt +1 -1
- ansible_test/_data/requirements/units.txt +1 -0
- ansible_test/_internal/__init__.py +6 -0
- ansible_test/_internal/ansible_util.py +3 -1
- ansible_test/_internal/become.py +1 -0
- ansible_test/_internal/bootstrap.py +1 -0
- ansible_test/_internal/cache.py +1 -0
- ansible_test/_internal/cgroup.py +1 -0
- ansible_test/_internal/ci/__init__.py +1 -0
- ansible_test/_internal/ci/azp.py +1 -0
- ansible_test/_internal/ci/local.py +1 -0
- ansible_test/_internal/classification/__init__.py +1 -0
- ansible_test/_internal/classification/common.py +1 -0
- ansible_test/_internal/classification/csharp.py +1 -0
- ansible_test/_internal/classification/powershell.py +1 -0
- ansible_test/_internal/classification/python.py +1 -0
- ansible_test/_internal/cli/__init__.py +1 -0
- ansible_test/_internal/cli/actions.py +1 -0
- ansible_test/_internal/cli/argparsing/__init__.py +1 -0
- ansible_test/_internal/cli/argparsing/actions.py +1 -0
- ansible_test/_internal/cli/argparsing/argcompletion.py +1 -0
- ansible_test/_internal/cli/argparsing/parsers.py +1 -0
- ansible_test/_internal/cli/commands/__init__.py +11 -5
- ansible_test/_internal/cli/commands/coverage/__init__.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/__init__.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/__init__.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/combine.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/expand.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/filter.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/generate.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/missing.py +1 -0
- ansible_test/_internal/cli/commands/coverage/combine.py +1 -0
- ansible_test/_internal/cli/commands/coverage/erase.py +1 -0
- ansible_test/_internal/cli/commands/coverage/html.py +1 -0
- ansible_test/_internal/cli/commands/coverage/report.py +1 -0
- ansible_test/_internal/cli/commands/coverage/xml.py +1 -0
- ansible_test/_internal/cli/commands/env.py +1 -0
- ansible_test/_internal/cli/commands/integration/__init__.py +1 -0
- ansible_test/_internal/cli/commands/integration/network.py +1 -0
- ansible_test/_internal/cli/commands/integration/posix.py +1 -0
- ansible_test/_internal/cli/commands/integration/windows.py +1 -0
- ansible_test/_internal/cli/commands/sanity.py +9 -0
- ansible_test/_internal/cli/commands/shell.py +1 -0
- ansible_test/_internal/cli/commands/units.py +1 -0
- ansible_test/_internal/cli/compat.py +1 -0
- ansible_test/_internal/cli/completers.py +1 -0
- ansible_test/_internal/cli/converters.py +1 -0
- ansible_test/_internal/cli/environments.py +52 -5
- ansible_test/_internal/cli/epilog.py +1 -0
- ansible_test/_internal/cli/parsers/__init__.py +1 -0
- ansible_test/_internal/cli/parsers/base_argument_parsers.py +1 -0
- ansible_test/_internal/cli/parsers/helpers.py +1 -0
- ansible_test/_internal/cli/parsers/host_config_parsers.py +1 -0
- ansible_test/_internal/cli/parsers/key_value_parsers.py +1 -0
- ansible_test/_internal/cli/parsers/value_parsers.py +1 -0
- ansible_test/_internal/commands/__init__.py +1 -0
- ansible_test/_internal/commands/coverage/__init__.py +3 -2
- ansible_test/_internal/commands/coverage/analyze/__init__.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/__init__.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/combine.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/expand.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/filter.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/generate.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/missing.py +1 -0
- ansible_test/_internal/commands/coverage/combine.py +2 -1
- ansible_test/_internal/commands/coverage/erase.py +1 -0
- ansible_test/_internal/commands/coverage/html.py +1 -0
- ansible_test/_internal/commands/coverage/report.py +1 -0
- ansible_test/_internal/commands/coverage/xml.py +1 -0
- ansible_test/_internal/commands/env/__init__.py +2 -0
- ansible_test/_internal/commands/integration/__init__.py +22 -5
- ansible_test/_internal/commands/integration/cloud/__init__.py +1 -0
- ansible_test/_internal/commands/integration/cloud/acme.py +2 -1
- ansible_test/_internal/commands/integration/cloud/aws.py +1 -0
- ansible_test/_internal/commands/integration/cloud/azure.py +1 -0
- ansible_test/_internal/commands/integration/cloud/cs.py +1 -0
- ansible_test/_internal/commands/integration/cloud/digitalocean.py +1 -0
- ansible_test/_internal/commands/integration/cloud/galaxy.py +3 -2
- ansible_test/_internal/commands/integration/cloud/hcloud.py +1 -0
- ansible_test/_internal/commands/integration/cloud/httptester.py +3 -2
- ansible_test/_internal/commands/integration/cloud/nios.py +2 -1
- ansible_test/_internal/commands/integration/cloud/opennebula.py +1 -0
- ansible_test/_internal/commands/integration/cloud/openshift.py +1 -0
- ansible_test/_internal/commands/integration/cloud/scaleway.py +1 -0
- ansible_test/_internal/commands/integration/cloud/vcenter.py +1 -0
- ansible_test/_internal/commands/integration/cloud/vultr.py +1 -0
- ansible_test/_internal/commands/integration/coverage.py +8 -2
- ansible_test/_internal/commands/integration/filters.py +1 -0
- ansible_test/_internal/commands/integration/network.py +1 -0
- ansible_test/_internal/commands/integration/posix.py +1 -0
- ansible_test/_internal/commands/integration/windows.py +1 -0
- ansible_test/_internal/commands/sanity/__init__.py +19 -2
- ansible_test/_internal/commands/sanity/ansible_doc.py +1 -0
- ansible_test/_internal/commands/sanity/bin_symlinks.py +1 -0
- ansible_test/_internal/commands/sanity/compile.py +1 -0
- ansible_test/_internal/commands/sanity/ignores.py +1 -0
- ansible_test/_internal/commands/sanity/import.py +1 -0
- ansible_test/_internal/commands/sanity/integration_aliases.py +12 -0
- ansible_test/_internal/commands/sanity/pep8.py +1 -0
- ansible_test/_internal/commands/sanity/pslint.py +1 -0
- ansible_test/_internal/commands/sanity/pylint.py +25 -26
- ansible_test/_internal/commands/sanity/shellcheck.py +1 -0
- ansible_test/_internal/commands/sanity/validate_modules.py +1 -0
- ansible_test/_internal/commands/sanity/yamllint.py +1 -0
- ansible_test/_internal/commands/shell/__init__.py +44 -4
- ansible_test/_internal/commands/units/__init__.py +5 -1
- ansible_test/_internal/compat/__init__.py +1 -0
- ansible_test/_internal/compat/packaging.py +1 -0
- ansible_test/_internal/compat/yaml.py +1 -0
- ansible_test/_internal/completion.py +1 -0
- ansible_test/_internal/config.py +23 -13
- ansible_test/_internal/connections.py +1 -0
- ansible_test/_internal/constants.py +1 -0
- ansible_test/_internal/containers.py +1 -0
- ansible_test/_internal/content_config.py +1 -0
- ansible_test/_internal/core_ci.py +1 -0
- ansible_test/_internal/coverage_util.py +11 -10
- ansible_test/_internal/data.py +1 -0
- ansible_test/_internal/debugging.py +166 -0
- ansible_test/_internal/delegation.py +22 -13
- ansible_test/_internal/dev/__init__.py +1 -0
- ansible_test/_internal/dev/container_probe.py +1 -0
- ansible_test/_internal/diff.py +3 -2
- ansible_test/_internal/docker_util.py +2 -1
- ansible_test/_internal/encoding.py +1 -0
- ansible_test/_internal/executor.py +1 -0
- ansible_test/_internal/git.py +1 -0
- ansible_test/_internal/host_configs.py +1 -0
- ansible_test/_internal/host_profiles.py +260 -16
- ansible_test/_internal/http.py +1 -0
- ansible_test/_internal/init.py +1 -0
- ansible_test/_internal/inventory.py +39 -3
- ansible_test/_internal/io.py +1 -0
- ansible_test/_internal/metadata.py +95 -4
- ansible_test/_internal/payload.py +1 -0
- ansible_test/_internal/processes.py +80 -0
- ansible_test/_internal/provider/__init__.py +1 -0
- ansible_test/_internal/provider/layout/__init__.py +1 -0
- ansible_test/_internal/provider/layout/ansible.py +1 -0
- ansible_test/_internal/provider/layout/collection.py +1 -0
- ansible_test/_internal/provider/layout/unsupported.py +1 -0
- ansible_test/_internal/provider/source/__init__.py +1 -0
- ansible_test/_internal/provider/source/git.py +1 -0
- ansible_test/_internal/provider/source/installed.py +1 -0
- ansible_test/_internal/provider/source/unsupported.py +1 -0
- ansible_test/_internal/provider/source/unversioned.py +1 -0
- ansible_test/_internal/provisioning.py +11 -4
- ansible_test/_internal/pypi_proxy.py +6 -5
- ansible_test/_internal/python_requirements.py +28 -0
- ansible_test/_internal/ssh.py +2 -5
- ansible_test/_internal/target.py +9 -0
- ansible_test/_internal/test.py +3 -2
- ansible_test/_internal/thread.py +3 -1
- ansible_test/_internal/timeout.py +2 -1
- ansible_test/_internal/util.py +41 -12
- ansible_test/_internal/util_common.py +18 -5
- ansible_test/_internal/venv.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/action-plugin-docs.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/changelog/sphinx.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/changelog.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/empty-init.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/line-endings.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-assert.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-get-exception.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-illegal-filenames.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-smart-quotes.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/replace-urlopen.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/runtime-metadata.py +28 -1
- ansible_test/_util/controller/sanity/code-smell/shebang.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/symlinks.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/use-argspec-type-path.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/use-compat-six.py +1 -0
- ansible_test/_util/controller/sanity/integration-aliases/yaml_to_json.py +2 -1
- ansible_test/_util/controller/sanity/pep8/current-ignore.txt +4 -0
- ansible_test/_util/controller/sanity/pylint/config/ansible-test-target.cfg +8 -5
- ansible_test/_util/controller/sanity/pylint/config/ansible-test.cfg +8 -5
- ansible_test/_util/controller/sanity/pylint/config/code-smell.cfg +8 -5
- ansible_test/_util/controller/sanity/pylint/config/collection.cfg +4 -5
- ansible_test/_util/controller/sanity/pylint/config/default.cfg +8 -7
- ansible_test/_util/controller/sanity/pylint/plugins/deprecated_calls.py +541 -0
- ansible_test/_util/controller/sanity/pylint/plugins/deprecated_comment.py +137 -0
- ansible_test/_util/controller/sanity/pylint/plugins/hide_unraisable.py +1 -0
- ansible_test/_util/controller/sanity/pylint/plugins/string_format.py +1 -8
- ansible_test/_util/controller/sanity/pylint/plugins/unwanted.py +1 -8
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py +55 -28
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/module_args.py +12 -5
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/schema.py +13 -2
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/utils.py +1 -0
- ansible_test/_util/controller/sanity/yamllint/yamllinter.py +35 -17
- ansible_test/_util/controller/tools/collection_detail.py +1 -0
- ansible_test/_util/controller/tools/yaml_to_json.py +2 -1
- ansible_test/_util/target/injector/python.py +8 -0
- ansible_test/_util/target/pytest/plugins/ansible_forked.py +6 -1
- ansible_test/_util/target/pytest/plugins/ansible_pytest_collections.py +2 -1
- ansible_test/_util/target/pytest/plugins/ansible_pytest_coverage.py +1 -0
- ansible_test/_util/target/sanity/compile/compile.py +1 -0
- ansible_test/_util/target/sanity/import/importer.py +15 -16
- ansible_test/_util/target/setup/bootstrap.sh +9 -20
- ansible_test/_util/target/setup/probe_cgroups.py +1 -0
- ansible_test/_util/target/setup/quiet_pip.py +1 -0
- ansible_test/_util/target/setup/requirements.py +38 -36
- ansible_test/_util/target/tools/virtualenvcheck.py +2 -1
- ansible_test/_util/target/tools/yamlcheck.py +2 -1
- ansible/compat/selectors.py +0 -32
- ansible/errors/yaml_strings.py +0 -138
- ansible/executor/action_write_locks.py +0 -44
- ansible/executor/discovery/python_target.py +0 -47
- ansible/executor/powershell/module_powershell_wrapper.ps1 +0 -86
- ansible/executor/powershell/module_script_wrapper.ps1 +0 -22
- ansible/module_utils/compat/importlib.py +0 -26
- ansible/module_utils/compat/selectors.py +0 -32
- ansible/module_utils/pycompat24.py +0 -73
- ansible/parsing/yaml/constructor.py +0 -178
- ansible/template/native_helpers.py +0 -251
- ansible/template/template.py +0 -43
- ansible/template/vars.py +0 -77
- ansible/utils/native_jinja.py +0 -11
- ansible/vars/fact_cache.py +0 -71
- ansible_core-2.18.7.dist-info/RECORD +0 -992
- ansible_test/_util/controller/sanity/pylint/plugins/deprecated.py +0 -411
- {ansible_core-2.18.7.dist-info → ansible_core-2.19.0.dist-info}/WHEEL +0 -0
- {ansible_core-2.18.7.dist-info → ansible_core-2.19.0.dist-info}/entry_points.txt +0 -0
- {ansible_core-2.18.7.dist-info → ansible_core-2.19.0.dist-info}/licenses/COPYING +0 -0
- {ansible_core-2.18.7.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/Apache-License.txt +0 -0
- {ansible_core-2.18.7.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/MIT-license.txt +0 -0
- {ansible_core-2.18.7.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/PSF-license.txt +0 -0
- {ansible_core-2.18.7.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/simplified_bsd.txt +0 -0
- {ansible_core-2.18.7.dist-info → ansible_core-2.19.0.dist-info}/top_level.txt +0 -0
ansible/parsing/dataloader.py
CHANGED
|
@@ -2,23 +2,28 @@
|
|
|
2
2
|
# Copyright: (c) 2017, Ansible Project
|
|
3
3
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
4
4
|
|
|
5
|
+
from __future__ import annotations
|
|
5
6
|
from __future__ import annotations
|
|
6
7
|
|
|
7
8
|
import copy
|
|
8
9
|
import os
|
|
9
10
|
import os.path
|
|
11
|
+
import pathlib
|
|
10
12
|
import re
|
|
11
13
|
import tempfile
|
|
12
14
|
import typing as t
|
|
13
15
|
|
|
14
16
|
from ansible import constants as C
|
|
15
17
|
from ansible.errors import AnsibleFileNotFound, AnsibleParserError
|
|
18
|
+
from ansible._internal._errors import _error_utils
|
|
16
19
|
from ansible.module_utils.basic import is_executable
|
|
20
|
+
from ansible._internal._datatag._tags import Origin, TrustedAsTemplate, SourceWasEncrypted
|
|
21
|
+
from ansible.module_utils._internal._datatag import AnsibleTagHelper
|
|
17
22
|
from ansible.module_utils.six import binary_type, text_type
|
|
18
23
|
from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text
|
|
19
24
|
from ansible.parsing.quoting import unquote
|
|
20
25
|
from ansible.parsing.utils.yaml import from_yaml
|
|
21
|
-
from ansible.parsing.vault import VaultLib, is_encrypted, is_encrypted_file,
|
|
26
|
+
from ansible.parsing.vault import VaultLib, is_encrypted, is_encrypted_file, PromptVaultSecret
|
|
22
27
|
from ansible.utils.path import unfrackpath
|
|
23
28
|
from ansible.utils.display import Display
|
|
24
29
|
|
|
@@ -32,7 +37,7 @@ RE_TASKS = re.compile(u'(?:^|%s)+tasks%s?$' % (os.path.sep, os.path.sep))
|
|
|
32
37
|
|
|
33
38
|
class DataLoader:
|
|
34
39
|
|
|
35
|
-
|
|
40
|
+
"""
|
|
36
41
|
The DataLoader class is used to load and parse YAML or JSON content,
|
|
37
42
|
either from a given file name or from a string that was previously
|
|
38
43
|
read in through other means. A Vault password can be specified, and
|
|
@@ -47,7 +52,7 @@ class DataLoader:
|
|
|
47
52
|
# optionally: dl.set_vault_secrets([('default', ansible.parsing.vault.PrompVaultSecret(...),)])
|
|
48
53
|
ds = dl.load('...')
|
|
49
54
|
ds = dl.load_from_file('/path/to/file')
|
|
50
|
-
|
|
55
|
+
"""
|
|
51
56
|
|
|
52
57
|
def __init__(self):
|
|
53
58
|
|
|
@@ -73,12 +78,19 @@ class DataLoader:
|
|
|
73
78
|
def set_vault_secrets(self, vault_secrets: list[tuple[str, PromptVaultSecret]] | None) -> None:
|
|
74
79
|
self._vault.secrets = vault_secrets
|
|
75
80
|
|
|
76
|
-
def load(
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
81
|
+
def load(
|
|
82
|
+
self,
|
|
83
|
+
data: str,
|
|
84
|
+
file_name: str | None = None, # DTFIX-FUTURE: consider deprecating this in favor of tagging Origin on data
|
|
85
|
+
show_content: bool = True, # DTFIX-FUTURE: consider future deprecation, but would need RedactAnnotatedSourceContext public
|
|
86
|
+
json_only: bool = False,
|
|
87
|
+
) -> t.Any:
|
|
88
|
+
"""Backwards compat for now"""
|
|
89
|
+
with _error_utils.RedactAnnotatedSourceContext.when(not show_content):
|
|
90
|
+
return from_yaml(data=data, file_name=file_name, json_only=json_only)
|
|
91
|
+
|
|
92
|
+
def load_from_file(self, file_name: str, cache: str = 'all', unsafe: bool = False, json_only: bool = False, trusted_as_template: bool = False) -> t.Any:
|
|
93
|
+
"""
|
|
82
94
|
Loads data from a file, which can contain either JSON or YAML.
|
|
83
95
|
|
|
84
96
|
:param file_name: The name of the file to load data from.
|
|
@@ -86,7 +98,7 @@ class DataLoader:
|
|
|
86
98
|
:param unsafe: If True, returns the parsed data as-is without deep copying.
|
|
87
99
|
:param json_only: If True, only loads JSON data from the file.
|
|
88
100
|
:return: The loaded data, optionally deep-copied for safety.
|
|
89
|
-
|
|
101
|
+
"""
|
|
90
102
|
|
|
91
103
|
# Resolve the file name
|
|
92
104
|
file_name = self.path_dwim(file_name)
|
|
@@ -98,16 +110,22 @@ class DataLoader:
|
|
|
98
110
|
if cache != 'none' and file_name in self._FILE_CACHE:
|
|
99
111
|
parsed_data = self._FILE_CACHE[file_name]
|
|
100
112
|
else:
|
|
101
|
-
|
|
102
|
-
(b_file_data, show_content) = self._get_file_contents(file_name)
|
|
113
|
+
file_data = self.get_text_file_contents(file_name)
|
|
103
114
|
|
|
104
|
-
|
|
105
|
-
|
|
115
|
+
if trusted_as_template:
|
|
116
|
+
file_data = TrustedAsTemplate().tag(file_data)
|
|
117
|
+
|
|
118
|
+
parsed_data = self.load(data=file_data, file_name=file_name, json_only=json_only)
|
|
119
|
+
|
|
120
|
+
# only tagging the container, used by include_vars to determine if vars should be shown or not
|
|
121
|
+
# this is a temporary measure until a proper data senitivity system is in place
|
|
122
|
+
if SourceWasEncrypted.is_tagged_on(file_data):
|
|
123
|
+
parsed_data = SourceWasEncrypted().tag(parsed_data)
|
|
106
124
|
|
|
107
125
|
# Cache the file contents for next time based on the cache option
|
|
108
126
|
if cache == 'all':
|
|
109
127
|
self._FILE_CACHE[file_name] = parsed_data
|
|
110
|
-
elif cache == 'vaulted' and
|
|
128
|
+
elif cache == 'vaulted' and SourceWasEncrypted.is_tagged_on(file_data):
|
|
111
129
|
self._FILE_CACHE[file_name] = parsed_data
|
|
112
130
|
|
|
113
131
|
# Return the parsed data, optionally deep-copied for safety
|
|
@@ -133,25 +151,51 @@ class DataLoader:
|
|
|
133
151
|
return os.listdir(path)
|
|
134
152
|
|
|
135
153
|
def is_executable(self, path: str) -> bool:
|
|
136
|
-
|
|
154
|
+
"""is the given path executable?"""
|
|
137
155
|
path = self.path_dwim(path)
|
|
138
156
|
return is_executable(path)
|
|
139
157
|
|
|
140
|
-
def _decrypt_if_vault_data(self,
|
|
141
|
-
|
|
158
|
+
def _decrypt_if_vault_data(self, b_data: bytes) -> tuple[bytes, bool]:
|
|
159
|
+
"""Decrypt b_vault_data if encrypted and return b_data and the show_content flag"""
|
|
160
|
+
|
|
161
|
+
if encrypted_source := is_encrypted(b_data):
|
|
162
|
+
b_data = self._vault.decrypt(b_data)
|
|
163
|
+
|
|
164
|
+
return b_data, not encrypted_source
|
|
165
|
+
|
|
166
|
+
def get_text_file_contents(self, file_name: str, encoding: str | None = None) -> str:
|
|
167
|
+
"""
|
|
168
|
+
Returns an `Origin` tagged string with the content of the specified (DWIM-expanded for relative) file path, decrypting if necessary.
|
|
169
|
+
Callers must only specify `encoding` when the user can configure it, as error messages in that case will imply configurability.
|
|
170
|
+
If `encoding` is not specified, UTF-8 will be used.
|
|
171
|
+
"""
|
|
172
|
+
bytes_content, source_was_plaintext = self._get_file_contents(file_name)
|
|
173
|
+
|
|
174
|
+
if encoding is None:
|
|
175
|
+
encoding = 'utf-8'
|
|
176
|
+
help_text = 'This file must be UTF-8 encoded.'
|
|
177
|
+
else:
|
|
178
|
+
help_text = 'Ensure the correct encoding was specified.'
|
|
179
|
+
|
|
180
|
+
try:
|
|
181
|
+
str_content = bytes_content.decode(encoding=encoding, errors='strict')
|
|
182
|
+
except UnicodeDecodeError:
|
|
183
|
+
str_content = bytes_content.decode(encoding=encoding, errors='surrogateescape')
|
|
142
184
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
185
|
+
display.deprecated(
|
|
186
|
+
msg=f"File {file_name!r} could not be decoded as {encoding!r}. Invalid content has been escaped.",
|
|
187
|
+
version="2.23",
|
|
188
|
+
# obj intentionally omitted since there's no value in showing its contents
|
|
189
|
+
help_text=help_text,
|
|
190
|
+
)
|
|
146
191
|
|
|
147
|
-
|
|
148
|
-
|
|
192
|
+
if not source_was_plaintext:
|
|
193
|
+
str_content = SourceWasEncrypted().tag(str_content)
|
|
149
194
|
|
|
150
|
-
|
|
151
|
-
return b_data, show_content
|
|
195
|
+
return AnsibleTagHelper.tag_copy(bytes_content, str_content)
|
|
152
196
|
|
|
153
197
|
def _get_file_contents(self, file_name: str) -> tuple[bytes, bool]:
|
|
154
|
-
|
|
198
|
+
"""
|
|
155
199
|
Reads the file contents from the given file name
|
|
156
200
|
|
|
157
201
|
If the contents are vault-encrypted, it will decrypt them and return
|
|
@@ -162,40 +206,41 @@ class DataLoader:
|
|
|
162
206
|
:raises AnsibleFileNotFound: if the file_name does not refer to a file
|
|
163
207
|
:raises AnsibleParserError: if we were unable to read the file
|
|
164
208
|
:return: Returns a byte string of the file contents
|
|
165
|
-
|
|
166
|
-
if not file_name or not isinstance(file_name,
|
|
167
|
-
raise
|
|
209
|
+
"""
|
|
210
|
+
if not file_name or not isinstance(file_name, str):
|
|
211
|
+
raise TypeError(f"Invalid filename {file_name!r}.")
|
|
168
212
|
|
|
169
|
-
|
|
170
|
-
# This is what we really want but have to fix unittests to make it pass
|
|
171
|
-
# if not os.path.exists(b_file_name) or not os.path.isfile(b_file_name):
|
|
172
|
-
if not self.path_exists(b_file_name):
|
|
173
|
-
raise AnsibleFileNotFound("Unable to retrieve file contents", file_name=file_name)
|
|
213
|
+
file_name = self.path_dwim(file_name)
|
|
174
214
|
|
|
175
215
|
try:
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
216
|
+
data = pathlib.Path(file_name).read_bytes()
|
|
217
|
+
except FileNotFoundError as ex:
|
|
218
|
+
# DTFIX-FUTURE: why not just let the builtin one fly?
|
|
219
|
+
raise AnsibleFileNotFound("Unable to retrieve file contents.", file_name=file_name) from ex
|
|
220
|
+
except OSError as ex:
|
|
221
|
+
raise AnsibleParserError(f"An error occurred while trying to read the file {file_name!r}.") from ex
|
|
222
|
+
|
|
223
|
+
data = Origin(path=file_name).tag(data)
|
|
224
|
+
|
|
225
|
+
return self._decrypt_if_vault_data(data)
|
|
181
226
|
|
|
182
227
|
def get_basedir(self) -> str:
|
|
183
|
-
|
|
228
|
+
""" returns the current basedir """
|
|
184
229
|
return self._basedir
|
|
185
230
|
|
|
186
231
|
def set_basedir(self, basedir: str) -> None:
|
|
187
|
-
|
|
232
|
+
""" sets the base directory, used to find files when a relative path is given """
|
|
188
233
|
|
|
189
234
|
if basedir is not None:
|
|
190
235
|
self._basedir = to_text(basedir)
|
|
191
236
|
|
|
192
237
|
def path_dwim(self, given: str) -> str:
|
|
193
|
-
|
|
238
|
+
"""
|
|
194
239
|
make relative paths work like folks expect.
|
|
195
|
-
|
|
240
|
+
"""
|
|
196
241
|
|
|
197
|
-
given = unquote(given)
|
|
198
242
|
given = to_text(given, errors='surrogate_or_strict')
|
|
243
|
+
given = unquote(given)
|
|
199
244
|
|
|
200
245
|
if given.startswith(to_text(os.path.sep)) or given.startswith(u'~'):
|
|
201
246
|
path = given
|
|
@@ -206,7 +251,7 @@ class DataLoader:
|
|
|
206
251
|
return unfrackpath(path, follow=False)
|
|
207
252
|
|
|
208
253
|
def _is_role(self, path: str) -> bool:
|
|
209
|
-
|
|
254
|
+
""" imperfect role detection, roles are still valid w/o tasks|meta/main.yml|yaml|etc """
|
|
210
255
|
|
|
211
256
|
b_path = to_bytes(path, errors='surrogate_or_strict')
|
|
212
257
|
b_path_dirname = os.path.dirname(b_path)
|
|
@@ -240,13 +285,13 @@ class DataLoader:
|
|
|
240
285
|
return False
|
|
241
286
|
|
|
242
287
|
def path_dwim_relative(self, path: str, dirname: str, source: str, is_role: bool = False) -> str:
|
|
243
|
-
|
|
288
|
+
"""
|
|
244
289
|
find one file in either a role or playbook dir with or without
|
|
245
290
|
explicitly named dirname subdirs
|
|
246
291
|
|
|
247
292
|
Used in action plugins and lookups to find supplemental files that
|
|
248
293
|
could be in either place.
|
|
249
|
-
|
|
294
|
+
"""
|
|
250
295
|
|
|
251
296
|
search = []
|
|
252
297
|
source = to_text(source, errors='surrogate_or_strict')
|
|
@@ -295,7 +340,7 @@ class DataLoader:
|
|
|
295
340
|
return candidate
|
|
296
341
|
|
|
297
342
|
def path_dwim_relative_stack(self, paths: list[str], dirname: str, source: str, is_role: bool = False) -> str:
|
|
298
|
-
|
|
343
|
+
"""
|
|
299
344
|
find one file in first path in stack taking roles into account and adding play basedir as fallback
|
|
300
345
|
|
|
301
346
|
:arg paths: A list of text strings which are the paths to look for the filename in.
|
|
@@ -305,7 +350,7 @@ class DataLoader:
|
|
|
305
350
|
:rtype: A text string
|
|
306
351
|
:returns: An absolute path to the filename ``source`` if found
|
|
307
352
|
:raises: An AnsibleFileNotFound Exception if the file is found to exist in the search paths
|
|
308
|
-
|
|
353
|
+
"""
|
|
309
354
|
b_dirname = to_bytes(dirname, errors='surrogate_or_strict')
|
|
310
355
|
b_source = to_bytes(source, errors='surrogate_or_strict')
|
|
311
356
|
|
|
@@ -353,7 +398,7 @@ class DataLoader:
|
|
|
353
398
|
return result
|
|
354
399
|
|
|
355
400
|
def _create_content_tempfile(self, content: str | bytes) -> str:
|
|
356
|
-
|
|
401
|
+
""" Create a tempfile containing defined content """
|
|
357
402
|
fd, content_tempfile = tempfile.mkstemp(dir=C.DEFAULT_LOCAL_TMP)
|
|
358
403
|
f = os.fdopen(fd, 'wb')
|
|
359
404
|
content = to_bytes(content)
|
|
@@ -392,19 +437,19 @@ class DataLoader:
|
|
|
392
437
|
# if the file is encrypted and no password was specified,
|
|
393
438
|
# the decrypt call would throw an error, but we check first
|
|
394
439
|
# since the decrypt function doesn't know the file name
|
|
395
|
-
data = f.read()
|
|
440
|
+
data = Origin(path=real_path).tag(f.read())
|
|
396
441
|
if not self._vault.secrets:
|
|
397
442
|
raise AnsibleParserError("A vault password or secret must be specified to decrypt %s" % to_native(file_path))
|
|
398
443
|
|
|
399
|
-
data = self._vault.decrypt(data
|
|
444
|
+
data = self._vault.decrypt(data)
|
|
400
445
|
# Make a temp file
|
|
401
446
|
real_path = self._create_content_tempfile(data)
|
|
402
447
|
self._tempfiles.add(real_path)
|
|
403
448
|
|
|
404
449
|
return real_path
|
|
405
450
|
|
|
406
|
-
except
|
|
407
|
-
raise AnsibleParserError("an error occurred while trying to read the file
|
|
451
|
+
except OSError as ex:
|
|
452
|
+
raise AnsibleParserError(f"an error occurred while trying to read the file {to_text(real_path)!r}.") from ex
|
|
408
453
|
|
|
409
454
|
def cleanup_tmp_file(self, file_path: str) -> None:
|
|
410
455
|
"""
|
ansible/parsing/mod_args.py
CHANGED
|
@@ -19,16 +19,18 @@ from __future__ import annotations
|
|
|
19
19
|
|
|
20
20
|
import ansible.constants as C
|
|
21
21
|
from ansible.errors import AnsibleParserError, AnsibleError, AnsibleAssertionError
|
|
22
|
-
from ansible.module_utils.
|
|
22
|
+
from ansible.module_utils._internal._datatag import AnsibleTagHelper
|
|
23
|
+
from ansible.module_utils.common.sentinel import Sentinel
|
|
23
24
|
from ansible.module_utils.common.text.converters import to_text
|
|
24
25
|
from ansible.parsing.splitter import parse_kv, split_args
|
|
26
|
+
from ansible.parsing.vault import EncryptedString
|
|
25
27
|
from ansible.plugins.loader import module_loader, action_loader
|
|
26
|
-
from ansible.
|
|
28
|
+
from ansible._internal._templating import _jinja_bits
|
|
29
|
+
from ansible.utils.display import Display
|
|
27
30
|
from ansible.utils.fqcn import add_internal_fqcns
|
|
28
|
-
from ansible.utils.sentinel import Sentinel
|
|
29
31
|
|
|
30
32
|
|
|
31
|
-
# modules
|
|
33
|
+
# modules formatted for user msg
|
|
32
34
|
_BUILTIN_RAW_PARAM_MODULES_SIMPLE = set([
|
|
33
35
|
'include_vars',
|
|
34
36
|
'include_tasks',
|
|
@@ -129,59 +131,64 @@ class ModuleArgsParser:
|
|
|
129
131
|
self._task_attrs.update(['local_action', 'static'])
|
|
130
132
|
self._task_attrs = frozenset(self._task_attrs)
|
|
131
133
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
def _split_module_string(self, module_string):
|
|
135
|
-
'''
|
|
134
|
+
def _split_module_string(self, module_string: str) -> tuple[str, str]:
|
|
135
|
+
"""
|
|
136
136
|
when module names are expressed like:
|
|
137
137
|
action: copy src=a dest=b
|
|
138
138
|
the first part of the string is the name of the module
|
|
139
139
|
and the rest are strings pertaining to the arguments.
|
|
140
|
-
|
|
140
|
+
"""
|
|
141
141
|
|
|
142
142
|
tokens = split_args(module_string)
|
|
143
143
|
if len(tokens) > 1:
|
|
144
|
-
|
|
144
|
+
result = (tokens[0].strip(), " ".join(tokens[1:]))
|
|
145
145
|
else:
|
|
146
|
-
|
|
146
|
+
result = (tokens[0].strip(), "")
|
|
147
|
+
|
|
148
|
+
return AnsibleTagHelper.tag_copy(module_string, result[0]), AnsibleTagHelper.tag_copy(module_string, result[1])
|
|
147
149
|
|
|
148
150
|
def _normalize_parameters(self, thing, action=None, additional_args=None):
|
|
149
|
-
|
|
151
|
+
"""
|
|
150
152
|
arguments can be fuzzy. Deal with all the forms.
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
additional_args = {} if additional_args is None else additional_args
|
|
153
|
+
"""
|
|
154
154
|
|
|
155
155
|
# final args are the ones we'll eventually return, so first update
|
|
156
156
|
# them with any additional args specified, which have lower priority
|
|
157
157
|
# than those which may be parsed/normalized next
|
|
158
158
|
final_args = dict()
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
final_args['_variable_params'] = additional_args
|
|
164
|
-
else:
|
|
165
|
-
raise AnsibleParserError("Complex args containing variables cannot use bare variables (without Jinja2 delimiters), "
|
|
166
|
-
"and must use the full variable style ('{{var_name}}')")
|
|
159
|
+
|
|
160
|
+
if additional_args is not Sentinel:
|
|
161
|
+
if isinstance(additional_args, str) and _jinja_bits.is_possibly_all_template(additional_args):
|
|
162
|
+
final_args['_variable_params'] = additional_args
|
|
167
163
|
elif isinstance(additional_args, dict):
|
|
168
164
|
final_args.update(additional_args)
|
|
165
|
+
elif additional_args is None:
|
|
166
|
+
Display().deprecated(
|
|
167
|
+
msg="Ignoring empty task `args` keyword.",
|
|
168
|
+
version="2.23",
|
|
169
|
+
help_text='A mapping or template which resolves to a mapping is required.',
|
|
170
|
+
obj=self._task_ds,
|
|
171
|
+
)
|
|
169
172
|
else:
|
|
170
|
-
raise AnsibleParserError(
|
|
173
|
+
raise AnsibleParserError(
|
|
174
|
+
message='The value of the task `args` keyword is invalid.',
|
|
175
|
+
help_text='A mapping or template which resolves to a mapping is required.',
|
|
176
|
+
obj=additional_args,
|
|
177
|
+
)
|
|
171
178
|
|
|
172
179
|
# how we normalize depends if we figured out what the module name is
|
|
173
180
|
# yet. If we have already figured it out, it's a 'new style' invocation.
|
|
174
181
|
# otherwise, it's not
|
|
175
182
|
|
|
176
183
|
if action is not None:
|
|
177
|
-
args = self._normalize_new_style_args(thing, action)
|
|
184
|
+
args = self._normalize_new_style_args(thing, action, additional_args)
|
|
178
185
|
else:
|
|
179
186
|
(action, args) = self._normalize_old_style_args(thing)
|
|
180
187
|
|
|
181
188
|
# this can occasionally happen, simplify
|
|
182
189
|
if args and 'args' in args:
|
|
183
190
|
tmp_args = args.pop('args')
|
|
184
|
-
if isinstance(tmp_args,
|
|
191
|
+
if isinstance(tmp_args, str):
|
|
185
192
|
tmp_args = parse_kv(tmp_args)
|
|
186
193
|
args.update(tmp_args)
|
|
187
194
|
|
|
@@ -204,8 +211,8 @@ class ModuleArgsParser:
|
|
|
204
211
|
|
|
205
212
|
return (action, final_args)
|
|
206
213
|
|
|
207
|
-
def _normalize_new_style_args(self, thing, action):
|
|
208
|
-
|
|
214
|
+
def _normalize_new_style_args(self, thing, action, additional_args):
|
|
215
|
+
"""
|
|
209
216
|
deals with fuzziness in new style module invocations
|
|
210
217
|
accepting key=value pairs and dictionaries, and returns
|
|
211
218
|
a dictionary of arguments
|
|
@@ -215,15 +222,29 @@ class ModuleArgsParser:
|
|
|
215
222
|
{'region': 'xyz'}, 'ec2'
|
|
216
223
|
standardized outputs like:
|
|
217
224
|
{ _raw_params: 'echo hi', _uses_shell: True }
|
|
218
|
-
|
|
225
|
+
"""
|
|
219
226
|
|
|
220
227
|
if isinstance(thing, dict):
|
|
221
228
|
# form is like: { xyz: { x: 2, y: 3 } }
|
|
222
229
|
args = thing
|
|
223
|
-
elif isinstance(thing,
|
|
230
|
+
elif isinstance(thing, str):
|
|
224
231
|
# form is like: copy: src=a dest=b
|
|
225
232
|
check_raw = action in FREEFORM_ACTIONS
|
|
226
233
|
args = parse_kv(thing, check_raw=check_raw)
|
|
234
|
+
args_keys = set(args) - {'_raw_params'}
|
|
235
|
+
|
|
236
|
+
if args_keys and additional_args is not Sentinel:
|
|
237
|
+
kv_args = ', '.join(repr(arg) for arg in sorted(args_keys))
|
|
238
|
+
|
|
239
|
+
Display().deprecated(
|
|
240
|
+
msg=f"Merging legacy k=v args ({kv_args}) into task args.",
|
|
241
|
+
help_text="Include all task args in the task `args` mapping.",
|
|
242
|
+
version="2.23",
|
|
243
|
+
obj=thing,
|
|
244
|
+
)
|
|
245
|
+
elif isinstance(thing, EncryptedString):
|
|
246
|
+
# k=v parsing intentionally omitted
|
|
247
|
+
args = dict(_raw_params=thing)
|
|
227
248
|
elif thing is None:
|
|
228
249
|
# this can happen with modules which take no params, like ping:
|
|
229
250
|
args = None
|
|
@@ -232,7 +253,7 @@ class ModuleArgsParser:
|
|
|
232
253
|
return args
|
|
233
254
|
|
|
234
255
|
def _normalize_old_style_args(self, thing):
|
|
235
|
-
|
|
256
|
+
"""
|
|
236
257
|
deals with fuzziness in old-style (action/local_action) module invocations
|
|
237
258
|
returns tuple of (module_name, dictionary_args)
|
|
238
259
|
|
|
@@ -242,13 +263,14 @@ class ModuleArgsParser:
|
|
|
242
263
|
{'module': 'ec2', 'x': 1 }
|
|
243
264
|
standardized outputs like:
|
|
244
265
|
('ec2', { 'x': 1} )
|
|
245
|
-
|
|
266
|
+
"""
|
|
246
267
|
|
|
247
268
|
action = None
|
|
248
269
|
args = None
|
|
249
270
|
|
|
250
271
|
if isinstance(thing, dict):
|
|
251
272
|
# form is like: action: { module: 'copy', src: 'a', dest: 'b' }
|
|
273
|
+
Display().deprecated("Using a mapping for `action` is deprecated.", version='2.23', help_text='Use a string value for `action`.', obj=thing)
|
|
252
274
|
thing = thing.copy()
|
|
253
275
|
if 'module' in thing:
|
|
254
276
|
action, module_args = self._split_module_string(thing['module'])
|
|
@@ -257,7 +279,7 @@ class ModuleArgsParser:
|
|
|
257
279
|
args.update(parse_kv(module_args, check_raw=check_raw))
|
|
258
280
|
del args['module']
|
|
259
281
|
|
|
260
|
-
elif isinstance(thing,
|
|
282
|
+
elif isinstance(thing, str):
|
|
261
283
|
# form is like: action: copy src=a dest=b
|
|
262
284
|
(action, args) = self._split_module_string(thing)
|
|
263
285
|
check_raw = action in FREEFORM_ACTIONS
|
|
@@ -270,13 +292,11 @@ class ModuleArgsParser:
|
|
|
270
292
|
return (action, args)
|
|
271
293
|
|
|
272
294
|
def parse(self, skip_action_validation=False):
|
|
273
|
-
|
|
295
|
+
"""
|
|
274
296
|
Given a task in one of the supported forms, parses and returns
|
|
275
297
|
returns the action, arguments, and delegate_to values for the
|
|
276
298
|
task, dealing with all sorts of levels of fuzziness.
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
thing = None
|
|
299
|
+
"""
|
|
280
300
|
|
|
281
301
|
action = None
|
|
282
302
|
delegate_to = self._task_ds.get('delegate_to', Sentinel)
|
|
@@ -285,14 +305,14 @@ class ModuleArgsParser:
|
|
|
285
305
|
# This is the standard YAML form for command-type modules. We grab
|
|
286
306
|
# the args and pass them in as additional arguments, which can/will
|
|
287
307
|
# be overwritten via dict updates from the other arg sources below
|
|
288
|
-
additional_args = self._task_ds.get('args',
|
|
308
|
+
additional_args = self._task_ds.get('args', Sentinel)
|
|
289
309
|
|
|
290
310
|
# We can have one of action, local_action, or module specified
|
|
291
311
|
# action
|
|
292
312
|
if 'action' in self._task_ds:
|
|
293
313
|
# an old school 'action' statement
|
|
294
314
|
thing = self._task_ds['action']
|
|
295
|
-
action, args = self._normalize_parameters(thing,
|
|
315
|
+
action, args = self._normalize_parameters(thing, additional_args=additional_args)
|
|
296
316
|
|
|
297
317
|
# local_action
|
|
298
318
|
if 'local_action' in self._task_ds:
|
|
@@ -301,12 +321,7 @@ class ModuleArgsParser:
|
|
|
301
321
|
raise AnsibleParserError("action and local_action are mutually exclusive", obj=self._task_ds)
|
|
302
322
|
thing = self._task_ds.get('local_action', '')
|
|
303
323
|
delegate_to = 'localhost'
|
|
304
|
-
action, args = self._normalize_parameters(thing,
|
|
305
|
-
|
|
306
|
-
if action is not None and not skip_action_validation:
|
|
307
|
-
context = _get_action_context(action, self._collection_list)
|
|
308
|
-
if context is not None and context.resolved:
|
|
309
|
-
self.resolved_action = context.resolved_fqcn
|
|
324
|
+
action, args = self._normalize_parameters(thing, additional_args=additional_args)
|
|
310
325
|
|
|
311
326
|
# module: <stuff> is the more new-style invocation
|
|
312
327
|
|
|
@@ -315,14 +330,13 @@ class ModuleArgsParser:
|
|
|
315
330
|
|
|
316
331
|
# walk the filtered input dictionary to see if we recognize a module name
|
|
317
332
|
for item, value in non_task_ds.items():
|
|
318
|
-
context = None
|
|
319
|
-
is_action_candidate = False
|
|
320
333
|
if item in BUILTIN_TASKS:
|
|
321
334
|
is_action_candidate = True
|
|
322
335
|
elif skip_action_validation:
|
|
323
336
|
is_action_candidate = True
|
|
324
337
|
else:
|
|
325
338
|
try:
|
|
339
|
+
# DTFIX-FUTURE: extract to a helper method, shared with Task.post_validate_args
|
|
326
340
|
context = _get_action_context(item, self._collection_list)
|
|
327
341
|
except AnsibleError as e:
|
|
328
342
|
if e.obj is None:
|
|
@@ -336,9 +350,6 @@ class ModuleArgsParser:
|
|
|
336
350
|
if action is not None:
|
|
337
351
|
raise AnsibleParserError("conflicting action statements: %s, %s" % (action, item), obj=self._task_ds)
|
|
338
352
|
|
|
339
|
-
if context is not None and context.resolved:
|
|
340
|
-
self.resolved_action = context.resolved_fqcn
|
|
341
|
-
|
|
342
353
|
action = item
|
|
343
354
|
thing = value
|
|
344
355
|
action, args = self._normalize_parameters(thing, action=action, additional_args=additional_args)
|
|
@@ -353,14 +364,5 @@ class ModuleArgsParser:
|
|
|
353
364
|
else:
|
|
354
365
|
raise AnsibleParserError("no module/action detected in task.",
|
|
355
366
|
obj=self._task_ds)
|
|
356
|
-
elif args.get('_raw_params', '') != '' and action not in RAW_PARAM_MODULES:
|
|
357
|
-
templar = Templar(loader=None)
|
|
358
|
-
raw_params = args.pop('_raw_params')
|
|
359
|
-
if templar.is_template(raw_params):
|
|
360
|
-
args['_variable_params'] = raw_params
|
|
361
|
-
else:
|
|
362
|
-
raise AnsibleParserError(
|
|
363
|
-
"this task '%s' has extra params, which is only allowed in the following modules: %s" % (action, ", ".join(RAW_PARAM_MODULES_SIMPLE)),
|
|
364
|
-
obj=self._task_ds)
|
|
365
367
|
|
|
366
|
-
return
|
|
368
|
+
return action, args, delegate_to
|