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/executor/task_result.py
CHANGED
|
@@ -4,78 +4,148 @@
|
|
|
4
4
|
|
|
5
5
|
from __future__ import annotations
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
import collections.abc as _c
|
|
8
|
+
import dataclasses
|
|
9
|
+
import functools
|
|
10
|
+
import typing as t
|
|
11
|
+
|
|
12
|
+
from ansible import constants
|
|
13
|
+
from ansible.utils import vars as _vars
|
|
9
14
|
from ansible.vars.clean import module_response_deepcopy, strip_internal_keys
|
|
15
|
+
from ansible.module_utils._internal import _messages
|
|
16
|
+
from ansible._internal import _collection_proxy
|
|
17
|
+
|
|
18
|
+
if t.TYPE_CHECKING:
|
|
19
|
+
from ansible.inventory.host import Host
|
|
20
|
+
from ansible.playbook.task import Task
|
|
10
21
|
|
|
11
22
|
_IGNORE = ('failed', 'skipped')
|
|
12
|
-
_PRESERVE =
|
|
13
|
-
_SUB_PRESERVE = {'_ansible_delegated_vars':
|
|
23
|
+
_PRESERVE = {'attempts', 'changed', 'retries', '_ansible_no_log', 'exception', 'warnings', 'deprecations'}
|
|
24
|
+
_SUB_PRESERVE = {'_ansible_delegated_vars': {'ansible_host', 'ansible_port', 'ansible_user', 'ansible_connection'}}
|
|
14
25
|
|
|
15
26
|
# stuff callbacks need
|
|
16
27
|
CLEAN_EXCEPTIONS = (
|
|
17
28
|
'_ansible_verbose_always', # for debug and other actions, to always expand data (pretty jsonification)
|
|
18
29
|
'_ansible_item_label', # to know actual 'item' variable
|
|
19
|
-
'_ansible_no_log', # jic we
|
|
30
|
+
'_ansible_no_log', # jic we didn't clean up well enough, DON'T LOG
|
|
20
31
|
'_ansible_verbose_override', # controls display of ansible_facts, gathering would be very noise with -v otherwise
|
|
21
32
|
)
|
|
22
33
|
|
|
23
34
|
|
|
24
|
-
|
|
25
|
-
|
|
35
|
+
@t.final
|
|
36
|
+
@dataclasses.dataclass(frozen=True, kw_only=True, slots=True)
|
|
37
|
+
class _WireTaskResult:
|
|
38
|
+
"""A thin version of `_RawTaskResult` which can be sent over the worker queue."""
|
|
39
|
+
|
|
40
|
+
host_name: str
|
|
41
|
+
task_uuid: str
|
|
42
|
+
return_data: _c.MutableMapping[str, object]
|
|
43
|
+
task_fields: _c.Mapping[str, object]
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class _BaseTaskResult:
|
|
47
|
+
"""
|
|
26
48
|
This class is responsible for interpreting the resulting data
|
|
27
49
|
from an executed task, and provides helper methods for determining
|
|
28
50
|
the result of a given task.
|
|
29
|
-
|
|
51
|
+
"""
|
|
30
52
|
|
|
31
|
-
def __init__(self, host, task, return_data, task_fields
|
|
32
|
-
self.
|
|
33
|
-
self.
|
|
53
|
+
def __init__(self, host: Host, task: Task, return_data: _c.MutableMapping[str, t.Any], task_fields: _c.Mapping[str, t.Any]) -> None:
|
|
54
|
+
self.__host = host
|
|
55
|
+
self.__task = task
|
|
56
|
+
self._return_data = return_data # FIXME: this should be immutable, but strategy result processing mutates it in some corner cases
|
|
57
|
+
self.__task_fields = task_fields
|
|
34
58
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
59
|
+
@property
|
|
60
|
+
def host(self) -> Host:
|
|
61
|
+
"""The host associated with this result."""
|
|
62
|
+
return self.__host
|
|
39
63
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
64
|
+
@property
|
|
65
|
+
def _host(self) -> Host:
|
|
66
|
+
"""Use the `host` property when supporting only ansible-core 2.19 or later."""
|
|
67
|
+
# deprecated: description='Deprecate `_host` in favor of `host`' core_version='2.23'
|
|
68
|
+
return self.__host
|
|
69
|
+
|
|
70
|
+
@property
|
|
71
|
+
def task(self) -> Task:
|
|
72
|
+
"""The task associated with this result."""
|
|
73
|
+
return self.__task
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def _task(self) -> Task:
|
|
77
|
+
"""Use the `task` property when supporting only ansible-core 2.19 or later."""
|
|
78
|
+
# deprecated: description='Deprecate `_task` in favor of `task`' core_version='2.23'
|
|
79
|
+
return self.__task
|
|
80
|
+
|
|
81
|
+
@property
|
|
82
|
+
def task_fields(self) -> _c.Mapping[str, t.Any]:
|
|
83
|
+
"""The task fields associated with this result."""
|
|
84
|
+
return self.__task_fields
|
|
85
|
+
|
|
86
|
+
@property
|
|
87
|
+
def _task_fields(self) -> _c.Mapping[str, t.Any]:
|
|
88
|
+
"""Use the `task_fields` property when supporting only ansible-core 2.19 or later."""
|
|
89
|
+
# deprecated: description='Deprecate `_task_fields` in favor of `task`' core_version='2.23'
|
|
90
|
+
return self.__task_fields
|
|
91
|
+
|
|
92
|
+
@property
|
|
93
|
+
def exception(self) -> _messages.ErrorSummary | None:
|
|
94
|
+
"""The error from this task result, if any."""
|
|
95
|
+
return self._return_data.get('exception')
|
|
96
|
+
|
|
97
|
+
@property
|
|
98
|
+
def warnings(self) -> _c.Sequence[_messages.WarningSummary]:
|
|
99
|
+
"""The warnings for this task, if any."""
|
|
100
|
+
return _collection_proxy.SequenceProxy(self._return_data.get('warnings') or [])
|
|
44
101
|
|
|
45
102
|
@property
|
|
46
|
-
def
|
|
47
|
-
|
|
103
|
+
def deprecations(self) -> _c.Sequence[_messages.DeprecationSummary]:
|
|
104
|
+
"""The deprecation warnings for this task, if any."""
|
|
105
|
+
return _collection_proxy.SequenceProxy(self._return_data.get('deprecations') or [])
|
|
106
|
+
|
|
107
|
+
@property
|
|
108
|
+
def _loop_results(self) -> list[_c.MutableMapping[str, t.Any]]:
|
|
109
|
+
"""Return a list of loop results. If no loop results are present, an empty list is returned."""
|
|
110
|
+
results = self._return_data.get('results')
|
|
111
|
+
|
|
112
|
+
if not isinstance(results, list):
|
|
113
|
+
return []
|
|
48
114
|
|
|
49
|
-
|
|
115
|
+
return results
|
|
116
|
+
|
|
117
|
+
@property
|
|
118
|
+
def task_name(self) -> str:
|
|
119
|
+
return str(self.task_fields.get('name', '')) or self.task.get_name()
|
|
120
|
+
|
|
121
|
+
def is_changed(self) -> bool:
|
|
50
122
|
return self._check_key('changed')
|
|
51
123
|
|
|
52
|
-
def is_skipped(self):
|
|
53
|
-
|
|
54
|
-
if 'results' in self._result:
|
|
55
|
-
results = self._result['results']
|
|
124
|
+
def is_skipped(self) -> bool:
|
|
125
|
+
if self._loop_results:
|
|
56
126
|
# Loop tasks are only considered skipped if all items were skipped.
|
|
57
127
|
# some squashed results (eg, dnf) are not dicts and can't be skipped individually
|
|
58
|
-
if
|
|
128
|
+
if all(isinstance(loop_res, dict) and loop_res.get('skipped', False) for loop_res in self._loop_results):
|
|
59
129
|
return True
|
|
60
130
|
|
|
61
131
|
# regular tasks and squashed non-dict results
|
|
62
|
-
return self.
|
|
132
|
+
return bool(self._return_data.get('skipped', False))
|
|
63
133
|
|
|
64
|
-
def is_failed(self):
|
|
65
|
-
if 'failed_when_result' in self.
|
|
66
|
-
'results' in self._result and True in [True for x in self._result['results'] if 'failed_when_result' in x]:
|
|
134
|
+
def is_failed(self) -> bool:
|
|
135
|
+
if 'failed_when_result' in self._return_data or any(isinstance(loop_res, dict) and 'failed_when_result' in loop_res for loop_res in self._loop_results):
|
|
67
136
|
return self._check_key('failed_when_result')
|
|
68
|
-
else:
|
|
69
|
-
return self._check_key('failed')
|
|
70
137
|
|
|
71
|
-
|
|
138
|
+
return self._check_key('failed')
|
|
139
|
+
|
|
140
|
+
def is_unreachable(self) -> bool:
|
|
72
141
|
return self._check_key('unreachable')
|
|
73
142
|
|
|
74
|
-
def needs_debugger(self, globally_enabled=False):
|
|
75
|
-
_debugger = self.
|
|
76
|
-
_ignore_errors =
|
|
143
|
+
def needs_debugger(self, globally_enabled: bool = False) -> bool:
|
|
144
|
+
_debugger = self.task_fields.get('debugger')
|
|
145
|
+
_ignore_errors = constants.TASK_DEBUGGER_IGNORE_ERRORS and self.task_fields.get('ignore_errors')
|
|
77
146
|
|
|
78
147
|
ret = False
|
|
148
|
+
|
|
79
149
|
if globally_enabled and ((self.is_failed() and not _ignore_errors) or self.is_unreachable()):
|
|
80
150
|
ret = True
|
|
81
151
|
|
|
@@ -92,62 +162,95 @@ class TaskResult:
|
|
|
92
162
|
|
|
93
163
|
return ret
|
|
94
164
|
|
|
95
|
-
def _check_key(self, key):
|
|
96
|
-
|
|
165
|
+
def _check_key(self, key: str) -> bool:
|
|
166
|
+
"""Fetch a specific named boolean value from the result; if missing, a logical OR of the value from nested loop results; False for non-loop results."""
|
|
167
|
+
if (value := self._return_data.get(key, ...)) is not ...:
|
|
168
|
+
return bool(value)
|
|
97
169
|
|
|
98
|
-
|
|
99
|
-
return self._result.get(key, False)
|
|
100
|
-
else:
|
|
101
|
-
flag = False
|
|
102
|
-
for res in self._result.get('results', []):
|
|
103
|
-
if isinstance(res, dict):
|
|
104
|
-
flag |= res.get(key, False)
|
|
105
|
-
return flag
|
|
170
|
+
return any(isinstance(result, dict) and result.get(key) for result in self._loop_results)
|
|
106
171
|
|
|
107
|
-
def clean_copy(self):
|
|
108
172
|
|
|
109
|
-
|
|
173
|
+
@t.final
|
|
174
|
+
class _RawTaskResult(_BaseTaskResult):
|
|
175
|
+
def as_wire_task_result(self) -> _WireTaskResult:
|
|
176
|
+
"""Return a `_WireTaskResult` from this instance."""
|
|
177
|
+
return _WireTaskResult(
|
|
178
|
+
host_name=self.host.name,
|
|
179
|
+
task_uuid=self.task._uuid,
|
|
180
|
+
return_data=self._return_data,
|
|
181
|
+
task_fields=self.task_fields,
|
|
182
|
+
)
|
|
110
183
|
|
|
111
|
-
|
|
112
|
-
|
|
184
|
+
def as_callback_task_result(self) -> CallbackTaskResult:
|
|
185
|
+
"""Return a `CallbackTaskResult` from this instance."""
|
|
186
|
+
ignore: tuple[str, ...]
|
|
113
187
|
|
|
114
188
|
# statuses are already reflected on the event type
|
|
115
|
-
if
|
|
189
|
+
if self.task and self.task.action in constants._ACTION_DEBUG:
|
|
116
190
|
# debug is verbose by default to display vars, no need to add invocation
|
|
117
191
|
ignore = _IGNORE + ('invocation',)
|
|
118
192
|
else:
|
|
119
193
|
ignore = _IGNORE
|
|
120
194
|
|
|
121
|
-
subset = {}
|
|
195
|
+
subset: dict[str, dict[str, object]] = {}
|
|
196
|
+
|
|
122
197
|
# preserve subset for later
|
|
123
|
-
for sub in _SUB_PRESERVE:
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
if isinstance(self.
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
# actually remove
|
|
143
|
-
for remove_key in ignore:
|
|
144
|
-
if remove_key in result._result:
|
|
145
|
-
del result._result[remove_key]
|
|
198
|
+
for sub, sub_keys in _SUB_PRESERVE.items():
|
|
199
|
+
sub_data = self._return_data.get(sub)
|
|
200
|
+
|
|
201
|
+
if isinstance(sub_data, dict):
|
|
202
|
+
subset[sub] = {key: value for key, value in sub_data.items() if key in sub_keys}
|
|
203
|
+
|
|
204
|
+
# DTFIX-FUTURE: is checking no_log here redundant now that we use _ansible_no_log everywhere?
|
|
205
|
+
if isinstance(self.task.no_log, bool) and self.task.no_log or self._return_data.get('_ansible_no_log'):
|
|
206
|
+
censored_result = censor_result(self._return_data)
|
|
207
|
+
|
|
208
|
+
if self._loop_results:
|
|
209
|
+
# maintain shape for loop results so callback behavior recognizes a loop was performed
|
|
210
|
+
censored_result.update(results=[
|
|
211
|
+
censor_result(loop_res) if isinstance(loop_res, dict) and loop_res.get('_ansible_no_log') else loop_res for loop_res in self._loop_results
|
|
212
|
+
])
|
|
213
|
+
|
|
214
|
+
return_data = censored_result
|
|
215
|
+
elif self._return_data:
|
|
216
|
+
return_data = {k: v for k, v in module_response_deepcopy(self._return_data).items() if k not in ignore}
|
|
146
217
|
|
|
147
218
|
# remove almost ALL internal keys, keep ones relevant to callback
|
|
148
|
-
strip_internal_keys(
|
|
219
|
+
strip_internal_keys(return_data, exceptions=CLEAN_EXCEPTIONS)
|
|
220
|
+
else:
|
|
221
|
+
return_data = {}
|
|
149
222
|
|
|
150
223
|
# keep subset
|
|
151
|
-
|
|
224
|
+
return_data.update(subset)
|
|
225
|
+
|
|
226
|
+
return CallbackTaskResult(self.host, self.task, return_data, self.task_fields)
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
@t.final
|
|
230
|
+
class CallbackTaskResult(_BaseTaskResult):
|
|
231
|
+
"""Public contract of TaskResult """
|
|
232
|
+
|
|
233
|
+
@property
|
|
234
|
+
def _result(self) -> _c.MutableMapping[str, t.Any]:
|
|
235
|
+
"""Use the `result` property when supporting only ansible-core 2.19 or later."""
|
|
236
|
+
# deprecated: description='Deprecate `_result` in favor of `result`' core_version='2.23'
|
|
237
|
+
return self.result
|
|
238
|
+
|
|
239
|
+
@functools.cached_property
|
|
240
|
+
def result(self) -> _c.MutableMapping[str, t.Any]:
|
|
241
|
+
"""
|
|
242
|
+
Returns a cached copy of the task result dictionary for consumption by callbacks.
|
|
243
|
+
Internal custom types are transformed to native Python types to facilitate access and serialization.
|
|
244
|
+
"""
|
|
245
|
+
return t.cast(_c.MutableMapping[str, t.Any], _vars.transform_to_native_types(self._return_data))
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
TaskResult = CallbackTaskResult
|
|
249
|
+
"""Compatibility name for the pre-2.19 callback-shaped TaskResult passed to callbacks."""
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
def censor_result(result: _c.Mapping[str, t.Any]) -> dict[str, t.Any]:
|
|
253
|
+
censored_result = {key: value for key in _PRESERVE if (value := result.get(key, ...)) is not ...}
|
|
254
|
+
censored_result.update(censored="the output has been hidden due to the fact that 'no_log: true' was specified for this result")
|
|
152
255
|
|
|
153
|
-
|
|
256
|
+
return censored_result
|
ansible/galaxy/__init__.py
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
|
19
19
|
#
|
|
20
20
|
########################################################################
|
|
21
|
-
|
|
21
|
+
""" This manages remote shared Ansible objects, mainly roles"""
|
|
22
22
|
|
|
23
23
|
from __future__ import annotations
|
|
24
24
|
|
|
@@ -40,7 +40,7 @@ def get_collections_galaxy_meta_info():
|
|
|
40
40
|
|
|
41
41
|
|
|
42
42
|
class Galaxy(object):
|
|
43
|
-
|
|
43
|
+
""" Keeps global galaxy info """
|
|
44
44
|
|
|
45
45
|
def __init__(self):
|
|
46
46
|
# TODO: eventually remove this as it contains a mismash of properties that aren't really global
|
ansible/galaxy/api.py
CHANGED
|
@@ -57,13 +57,13 @@ def should_retry_error(exception):
|
|
|
57
57
|
if isinstance(exception, GalaxyError) and exception.http_code in RETRY_HTTP_ERROR_CODES:
|
|
58
58
|
return True
|
|
59
59
|
|
|
60
|
-
if isinstance(exception, AnsibleError) and (
|
|
60
|
+
if isinstance(exception, AnsibleError) and (cause := exception.__cause__):
|
|
61
61
|
# URLError is often a proxy for an underlying error, handle wrapped exceptions
|
|
62
|
-
if isinstance(
|
|
63
|
-
|
|
62
|
+
if isinstance(cause, URLError):
|
|
63
|
+
cause = cause.reason
|
|
64
64
|
|
|
65
65
|
# Handle common URL related errors
|
|
66
|
-
if isinstance(
|
|
66
|
+
if isinstance(cause, (TimeoutError, BadStatusLine, IncompleteRead)):
|
|
67
67
|
return True
|
|
68
68
|
|
|
69
69
|
return False
|
|
@@ -92,7 +92,7 @@ def g_connect(versions):
|
|
|
92
92
|
try:
|
|
93
93
|
data = self._call_galaxy(n_url, method='GET', error_context_msg=error_context_msg, cache=True)
|
|
94
94
|
except (AnsibleError, GalaxyError, ValueError, KeyError) as err:
|
|
95
|
-
# Either the URL
|
|
95
|
+
# Either the URL doesn't exist, or other error. Or the URL exists, but isn't a galaxy API
|
|
96
96
|
# root (not JSON, no 'available_versions') so try appending '/api/'
|
|
97
97
|
if n_url.endswith('/api') or n_url.endswith('/api/'):
|
|
98
98
|
raise
|
|
@@ -138,7 +138,7 @@ def g_connect(versions):
|
|
|
138
138
|
'The v2 Ansible Galaxy API is deprecated and no longer supported. '
|
|
139
139
|
'Ensure that you have configured the ansible-galaxy CLI to utilize an '
|
|
140
140
|
'updated and supported version of Ansible Galaxy.',
|
|
141
|
-
version='2.20'
|
|
141
|
+
version='2.20',
|
|
142
142
|
)
|
|
143
143
|
|
|
144
144
|
return method(self, *args, **kwargs)
|
|
@@ -337,10 +337,7 @@ class GalaxyAPI:
|
|
|
337
337
|
if not isinstance(other_galaxy_api, self.__class__):
|
|
338
338
|
return NotImplemented
|
|
339
339
|
|
|
340
|
-
return
|
|
341
|
-
self._priority > other_galaxy_api._priority or
|
|
342
|
-
self.name < self.name
|
|
343
|
-
)
|
|
340
|
+
return self._priority > other_galaxy_api._priority
|
|
344
341
|
|
|
345
342
|
@property # type: ignore[misc] # https://github.com/python/mypy/issues/1362
|
|
346
343
|
@g_connect(['v1', 'v2', 'v3'])
|
|
@@ -408,11 +405,8 @@ class GalaxyAPI:
|
|
|
408
405
|
method=method, timeout=self._server_timeout, http_agent=user_agent(), follow_redirects='safe')
|
|
409
406
|
except HTTPError as e:
|
|
410
407
|
raise GalaxyError(e, error_context_msg)
|
|
411
|
-
except Exception as
|
|
412
|
-
raise AnsibleError(
|
|
413
|
-
"Unknown error when attempting to call Galaxy at '%s': %s" % (url, to_native(e)),
|
|
414
|
-
orig_exc=e
|
|
415
|
-
)
|
|
408
|
+
except Exception as ex:
|
|
409
|
+
raise AnsibleError(f"Unknown error when attempting to call Galaxy at {url!r}.") from ex
|
|
416
410
|
|
|
417
411
|
resp_data = to_text(resp.read(), errors='surrogate_or_strict')
|
|
418
412
|
try:
|
|
@@ -471,8 +465,8 @@ class GalaxyAPI:
|
|
|
471
465
|
resp = open_url(url, data=args, validate_certs=self.validate_certs, method="POST", http_agent=user_agent(), timeout=self._server_timeout)
|
|
472
466
|
except HTTPError as e:
|
|
473
467
|
raise GalaxyError(e, 'Attempting to authenticate to galaxy')
|
|
474
|
-
except Exception as
|
|
475
|
-
raise AnsibleError('Unable to authenticate to galaxy
|
|
468
|
+
except Exception as ex:
|
|
469
|
+
raise AnsibleError('Unable to authenticate to galaxy.') from ex
|
|
476
470
|
|
|
477
471
|
data = json.loads(to_text(resp.read(), errors='surrogate_or_strict'))
|
|
478
472
|
return data
|
|
@@ -817,8 +811,17 @@ class GalaxyAPI:
|
|
|
817
811
|
|
|
818
812
|
signatures = data.get('signatures') or []
|
|
819
813
|
|
|
814
|
+
download_url_info = urlparse(data['download_url'])
|
|
815
|
+
if not download_url_info.scheme and not download_url_info.path.startswith('/'):
|
|
816
|
+
# galaxy does a lot of redirects, with much more complex pathing than we use
|
|
817
|
+
# within this codebase, without updating _call_galaxy to be able to return
|
|
818
|
+
# the final URL, we can't reliably build a relative URL.
|
|
819
|
+
raise AnsibleError(f'Invalid non absolute download_url: {data["download_url"]}')
|
|
820
|
+
|
|
821
|
+
download_url = urljoin(self.api_server, data['download_url'])
|
|
822
|
+
|
|
820
823
|
return CollectionVersionMetadata(data['namespace']['name'], data['collection']['name'], data['version'],
|
|
821
|
-
|
|
824
|
+
download_url, data['artifact']['sha256'],
|
|
822
825
|
data['metadata']['dependencies'], data['href'], signatures)
|
|
823
826
|
|
|
824
827
|
@g_connect(['v2', 'v3'])
|
|
@@ -874,7 +877,7 @@ class GalaxyAPI:
|
|
|
874
877
|
except GalaxyError as err:
|
|
875
878
|
if err.http_code != 404:
|
|
876
879
|
raise
|
|
877
|
-
# v3 doesn't raise a 404 so we need to
|
|
880
|
+
# v3 doesn't raise a 404 so we need to mimic the empty response from APIs that do.
|
|
878
881
|
return []
|
|
879
882
|
|
|
880
883
|
if 'data' in data:
|
|
@@ -896,12 +899,10 @@ class GalaxyAPI:
|
|
|
896
899
|
if not next_link:
|
|
897
900
|
break
|
|
898
901
|
elif relative_link:
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
versions_url = urljoin(versions_url, urlparse(versions_url).path)
|
|
904
|
-
next_link = versions_url.replace(versions_url_info.path, next_link)
|
|
902
|
+
next_link_info = urlparse(next_link)
|
|
903
|
+
if not next_link_info.scheme and not next_link_info.path.startswith('/'):
|
|
904
|
+
raise AnsibleError(f'Invalid non absolute pagination link: {next_link}')
|
|
905
|
+
next_link = urljoin(self.api_server, next_link)
|
|
905
906
|
|
|
906
907
|
data = self._call_galaxy(to_native(next_link, errors='surrogate_or_strict'),
|
|
907
908
|
error_context_msg=error_context_msg, cache=True, cache_key=cache_key)
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
|
|
6
6
|
from __future__ import annotations
|
|
7
7
|
|
|
8
|
-
import errno
|
|
9
8
|
import fnmatch
|
|
10
9
|
import functools
|
|
11
10
|
import glob
|
|
@@ -31,6 +30,7 @@ from dataclasses import dataclass
|
|
|
31
30
|
from hashlib import sha256
|
|
32
31
|
from io import BytesIO
|
|
33
32
|
from importlib.metadata import distribution
|
|
33
|
+
from importlib.resources import files
|
|
34
34
|
from itertools import chain
|
|
35
35
|
|
|
36
36
|
try:
|
|
@@ -85,7 +85,6 @@ if t.TYPE_CHECKING:
|
|
|
85
85
|
FilesManifestType = t.Dict[t.Literal['files', 'format'], t.Union[t.List[FileManifestEntryType], int]]
|
|
86
86
|
|
|
87
87
|
import ansible.constants as C
|
|
88
|
-
from ansible.compat.importlib_resources import files
|
|
89
88
|
from ansible.errors import AnsibleError
|
|
90
89
|
from ansible.galaxy.api import GalaxyAPI
|
|
91
90
|
from ansible.galaxy.collection.concrete_artifact_manager import (
|
|
@@ -126,13 +125,13 @@ from ansible.galaxy.dependency_resolution.dataclasses import (
|
|
|
126
125
|
from ansible.galaxy.dependency_resolution.versioning import meets_requirements
|
|
127
126
|
from ansible.plugins.loader import get_all_plugin_loaders
|
|
128
127
|
from ansible.module_utils.common.file import S_IRWU_RG_RO, S_IRWXU_RXG_RXO, S_IXANY
|
|
128
|
+
from ansible.module_utils.common.sentinel import Sentinel
|
|
129
129
|
from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text
|
|
130
130
|
from ansible.module_utils.common.collections import is_sequence
|
|
131
131
|
from ansible.module_utils.common.yaml import yaml_dump
|
|
132
132
|
from ansible.utils.collection_loader import AnsibleCollectionRef
|
|
133
133
|
from ansible.utils.display import Display
|
|
134
134
|
from ansible.utils.hashing import secure_hash, secure_hash_s
|
|
135
|
-
from ansible.utils.sentinel import Sentinel
|
|
136
135
|
|
|
137
136
|
|
|
138
137
|
display = Display()
|
|
@@ -201,9 +200,9 @@ class CollectionSignatureError(Exception):
|
|
|
201
200
|
|
|
202
201
|
# FUTURE: expose actual verify result details for a collection on this object, maybe reimplement as dataclass on py3.8+
|
|
203
202
|
class CollectionVerifyResult:
|
|
204
|
-
def __init__(self, collection_name
|
|
205
|
-
self.collection_name = collection_name
|
|
206
|
-
self.success = True
|
|
203
|
+
def __init__(self, collection_name: str) -> None:
|
|
204
|
+
self.collection_name = collection_name
|
|
205
|
+
self.success = True
|
|
207
206
|
|
|
208
207
|
|
|
209
208
|
def verify_local_collection(local_collection, remote_collection, artifacts_manager):
|
|
@@ -1433,9 +1432,6 @@ def find_existing_collections(path_filter, artifacts_manager, namespace_filter=N
|
|
|
1433
1432
|
:param path: Collection dirs layout search path.
|
|
1434
1433
|
:param artifacts_manager: Artifacts manager.
|
|
1435
1434
|
"""
|
|
1436
|
-
if files is None:
|
|
1437
|
-
raise AnsibleError('importlib_resources is not installed and is required')
|
|
1438
|
-
|
|
1439
1435
|
if path_filter and not is_sequence(path_filter):
|
|
1440
1436
|
path_filter = [path_filter]
|
|
1441
1437
|
if namespace_filter and not is_sequence(namespace_filter):
|
|
@@ -1692,11 +1688,7 @@ def _extract_tar_dir(tar, dirname, b_dest):
|
|
|
1692
1688
|
b_dir_path = os.path.join(b_dest, to_bytes(dirname, errors='surrogate_or_strict'))
|
|
1693
1689
|
|
|
1694
1690
|
b_parent_path = os.path.dirname(b_dir_path)
|
|
1695
|
-
|
|
1696
|
-
os.makedirs(b_parent_path, mode=S_IRWXU_RXG_RXO)
|
|
1697
|
-
except OSError as e:
|
|
1698
|
-
if e.errno != errno.EEXIST:
|
|
1699
|
-
raise
|
|
1691
|
+
os.makedirs(b_parent_path, mode=S_IRWXU_RXG_RXO, exist_ok=True)
|
|
1700
1692
|
|
|
1701
1693
|
if tar_member.type == tarfile.SYMTYPE:
|
|
1702
1694
|
b_link_path = to_bytes(tar_member.linkname, errors='surrogate_or_strict')
|
|
@@ -35,10 +35,10 @@ from ansible.module_utils.common.text.converters import to_bytes, to_native, to_
|
|
|
35
35
|
from ansible.module_utils.api import retry_with_delays_and_condition
|
|
36
36
|
from ansible.module_utils.api import generate_jittered_backoff
|
|
37
37
|
from ansible.module_utils.common.process import get_bin_path
|
|
38
|
+
from ansible.module_utils.common.sentinel import Sentinel
|
|
38
39
|
from ansible.module_utils.common.yaml import yaml_load
|
|
39
40
|
from ansible.module_utils.urls import open_url
|
|
40
41
|
from ansible.utils.display import Display
|
|
41
|
-
from ansible.utils.sentinel import Sentinel
|
|
42
42
|
|
|
43
43
|
import ansible.constants as C
|
|
44
44
|
|
|
@@ -449,9 +449,9 @@ def _extract_collection_from_git(repo_url, coll_ver, b_path):
|
|
|
449
449
|
except subprocess.CalledProcessError as proc_err:
|
|
450
450
|
raise AnsibleError( # should probably be LookupError
|
|
451
451
|
'Failed to switch a cloned Git repo `{repo_url!s}` '
|
|
452
|
-
'to the requested revision `{
|
|
452
|
+
'to the requested revision `{revision!s}`.'.
|
|
453
453
|
format(
|
|
454
|
-
|
|
454
|
+
revision=to_native(version),
|
|
455
455
|
repo_url=to_native(git_url),
|
|
456
456
|
),
|
|
457
457
|
) from proc_err
|
|
@@ -485,16 +485,13 @@ def _download_file(url, b_path, expected_hash, validate_certs, token=None, timeo
|
|
|
485
485
|
display.display("Downloading %s to %s" % (url, to_text(b_tarball_dir)))
|
|
486
486
|
# NOTE: Galaxy redirects downloads to S3 which rejects the request
|
|
487
487
|
# NOTE: if an Authorization header is attached so don't redirect it
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
)
|
|
496
|
-
except Exception as err:
|
|
497
|
-
raise AnsibleError(to_native(err), orig_exc=err)
|
|
488
|
+
resp = open_url(
|
|
489
|
+
to_native(url, errors='surrogate_or_strict'),
|
|
490
|
+
validate_certs=validate_certs,
|
|
491
|
+
headers=None if token is None else token.headers(),
|
|
492
|
+
unredirected_headers=['Authorization'], http_agent=user_agent(),
|
|
493
|
+
timeout=timeout
|
|
494
|
+
)
|
|
498
495
|
|
|
499
496
|
with open(b_file_path, 'wb') as download_file: # type: t.BinaryIO
|
|
500
497
|
actual_hash = _consume_file(resp, write_to=download_file)
|
|
@@ -659,14 +656,8 @@ def _get_json_from_installed_dir(
|
|
|
659
656
|
try:
|
|
660
657
|
with open(b_json_filepath, 'rb') as manifest_fd:
|
|
661
658
|
b_json_text = manifest_fd.read()
|
|
662
|
-
except
|
|
663
|
-
raise LookupError(
|
|
664
|
-
"The collection {manifest!s} path '{path!s}' does not exist.".
|
|
665
|
-
format(
|
|
666
|
-
manifest=filename,
|
|
667
|
-
path=to_native(b_json_filepath),
|
|
668
|
-
)
|
|
669
|
-
)
|
|
659
|
+
except OSError as ex:
|
|
660
|
+
raise LookupError(f"The collection {filename!r} path {to_text(b_json_filepath)!r} does not exist.") from ex
|
|
670
661
|
|
|
671
662
|
manifest_txt = to_text(b_json_text, errors='surrogate_or_strict')
|
|
672
663
|
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
from __future__ import annotations
|
|
8
8
|
|
|
9
9
|
import os
|
|
10
|
+
import pathlib
|
|
10
11
|
import typing as t
|
|
11
12
|
|
|
12
13
|
from collections import namedtuple
|
|
@@ -25,6 +26,8 @@ if t.TYPE_CHECKING:
|
|
|
25
26
|
'_ComputedReqKindsMixin',
|
|
26
27
|
)
|
|
27
28
|
|
|
29
|
+
import ansible
|
|
30
|
+
import ansible.release
|
|
28
31
|
|
|
29
32
|
from ansible.errors import AnsibleError, AnsibleAssertionError
|
|
30
33
|
from ansible.galaxy.api import GalaxyAPI
|
|
@@ -39,6 +42,7 @@ _ALLOW_CONCRETE_POINTER_IN_SOURCE = False # NOTE: This is a feature flag
|
|
|
39
42
|
_GALAXY_YAML = b'galaxy.yml'
|
|
40
43
|
_MANIFEST_JSON = b'MANIFEST.json'
|
|
41
44
|
_SOURCE_METADATA_FILE = b'GALAXY.yml'
|
|
45
|
+
_ANSIBLE_PACKAGE_PATH = pathlib.Path(ansible.__file__).parent
|
|
42
46
|
|
|
43
47
|
display = Display()
|
|
44
48
|
|
|
@@ -224,6 +228,13 @@ class _ComputedReqKindsMixin:
|
|
|
224
228
|
if dir_path.endswith(to_bytes(os.path.sep)):
|
|
225
229
|
dir_path = dir_path.rstrip(to_bytes(os.path.sep))
|
|
226
230
|
if not _is_collection_dir(dir_path):
|
|
231
|
+
dir_pathlib = pathlib.Path(to_text(dir_path))
|
|
232
|
+
|
|
233
|
+
# special handling for bundled collections without manifests, e.g., ansible._protomatter
|
|
234
|
+
if dir_pathlib.is_relative_to(_ANSIBLE_PACKAGE_PATH):
|
|
235
|
+
req_name = f'{dir_pathlib.parent.name}.{dir_pathlib.name}'
|
|
236
|
+
return cls(req_name, ansible.release.__version__, dir_path, 'dir', None)
|
|
237
|
+
|
|
227
238
|
display.warning(
|
|
228
239
|
u"Collection at '{path!s}' does not have a {manifest_json!s} "
|
|
229
240
|
u'file, nor has it {galaxy_yml!s}: cannot detect version.'.
|
|
@@ -578,10 +589,9 @@ class _ComputedReqKindsMixin:
|
|
|
578
589
|
|
|
579
590
|
See https://github.com/ansible/ansible/pull/81606 for extra context.
|
|
580
591
|
"""
|
|
581
|
-
|
|
582
|
-
return
|
|
583
|
-
|
|
584
|
-
version_string.startswith(('<', '>', '!='))
|
|
592
|
+
version_spec_start_char = self.ver[0]
|
|
593
|
+
return version_spec_start_char.isdigit() or not (
|
|
594
|
+
version_spec_start_char.startswith(('<', '>', '!', '*'))
|
|
585
595
|
)
|
|
586
596
|
|
|
587
597
|
@property
|