ansible-core 2.18.5rc1__py3-none-any.whl → 2.19.0b2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ansible/_internal/__init__.py +53 -0
- ansible/_internal/_ansiballz.py +265 -0
- ansible/_internal/_collection_proxy.py +47 -0
- ansible/_internal/_datatag/__init__.py +0 -0
- ansible/_internal/_datatag/_tags.py +130 -0
- ansible/_internal/_datatag/_utils.py +19 -0
- ansible/_internal/_datatag/_wrappers.py +33 -0
- ansible/_internal/_errors/__init__.py +0 -0
- ansible/_internal/_errors/_captured.py +128 -0
- ansible/_internal/_errors/_handler.py +91 -0
- ansible/_internal/_errors/_utils.py +310 -0
- ansible/_internal/_json/__init__.py +203 -0
- ansible/_internal/_json/_legacy_encoder.py +34 -0
- ansible/_internal/_json/_profiles/__init__.py +0 -0
- ansible/_internal/_json/_profiles/_cache_persistence.py +55 -0
- ansible/_internal/_json/_profiles/_inventory_legacy.py +40 -0
- ansible/_internal/_json/_profiles/_legacy.py +197 -0
- ansible/_internal/_locking.py +21 -0
- ansible/_internal/_plugins/__init__.py +0 -0
- ansible/_internal/_plugins/_cache.py +57 -0
- ansible/_internal/_task.py +78 -0
- ansible/_internal/_templating/__init__.py +10 -0
- ansible/_internal/_templating/_access.py +86 -0
- ansible/_internal/_templating/_chain_templar.py +63 -0
- ansible/_internal/_templating/_datatag.py +95 -0
- ansible/_internal/_templating/_engine.py +588 -0
- ansible/_internal/_templating/_errors.py +28 -0
- ansible/_internal/_templating/_jinja_bits.py +1066 -0
- ansible/_internal/_templating/_jinja_common.py +332 -0
- ansible/_internal/_templating/_jinja_patches.py +44 -0
- ansible/_internal/_templating/_jinja_plugins.py +345 -0
- ansible/_internal/_templating/_lazy_containers.py +633 -0
- ansible/_internal/_templating/_marker_behaviors.py +103 -0
- ansible/_internal/_templating/_transform.py +63 -0
- ansible/_internal/_templating/_utils.py +107 -0
- ansible/_internal/_wrapt.py +1052 -0
- ansible/_internal/_yaml/__init__.py +0 -0
- ansible/_internal/_yaml/_constructor.py +240 -0
- ansible/_internal/_yaml/_dumper.py +62 -0
- ansible/_internal/_yaml/_errors.py +166 -0
- ansible/_internal/_yaml/_loader.py +66 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/README.md +11 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/action/debug.py +36 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/apply_trust.py +19 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/dump_object.py +18 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/finalize.py +16 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/origin.py +18 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/python_literal_eval.py +24 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/python_literal_eval.yml +33 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/tag_names.py +16 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/true_type.py +17 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/unmask.py +49 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/lookup/config.py +21 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/lookup/config.yml +2 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged.py +15 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged.yml +19 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged_with.py +18 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged_with.yml +19 -0
- ansible/cli/__init__.py +159 -89
- ansible/cli/_ssh_askpass.py +47 -0
- ansible/cli/adhoc.py +14 -7
- ansible/cli/arguments/option_helpers.py +154 -7
- ansible/cli/config.py +43 -68
- ansible/cli/console.py +10 -8
- ansible/cli/doc.py +62 -53
- ansible/cli/galaxy.py +27 -20
- ansible/cli/inventory.py +28 -26
- ansible/cli/playbook.py +4 -12
- ansible/cli/pull.py +51 -11
- ansible/cli/scripts/ansible_connection_cli_stub.py +7 -7
- ansible/cli/vault.py +12 -11
- ansible/compat/__init__.py +2 -2
- ansible/config/base.yml +166 -112
- ansible/config/manager.py +52 -49
- ansible/constants.py +3 -4
- ansible/errors/__init__.py +277 -235
- ansible/executor/interpreter_discovery.py +28 -149
- ansible/executor/module_common.py +426 -493
- ansible/executor/play_iterator.py +22 -27
- ansible/executor/playbook_executor.py +11 -11
- ansible/executor/powershell/async_watchdog.ps1 +97 -102
- ansible/executor/powershell/async_wrapper.ps1 +202 -151
- ansible/executor/powershell/become_wrapper.ps1 +89 -144
- ansible/executor/powershell/bootstrap_wrapper.ps1 +24 -9
- ansible/executor/powershell/coverage_wrapper.ps1 +82 -135
- ansible/executor/powershell/exec_wrapper.ps1 +462 -196
- ansible/executor/powershell/module_manifest.py +417 -265
- ansible/executor/powershell/module_wrapper.ps1 +169 -186
- ansible/executor/powershell/psrp_fetch_file.ps1 +41 -0
- ansible/executor/powershell/psrp_put_file.ps1 +122 -0
- ansible/executor/powershell/winrm_fetch_file.ps1 +46 -0
- ansible/executor/powershell/winrm_put_file.ps1 +36 -0
- ansible/executor/process/worker.py +161 -96
- ansible/executor/stats.py +5 -5
- ansible/executor/task_executor.py +268 -258
- ansible/executor/task_queue_manager.py +124 -90
- ansible/executor/task_result.py +183 -78
- ansible/galaxy/__init__.py +2 -2
- ansible/galaxy/api.py +22 -18
- ansible/galaxy/collection/__init__.py +1 -1
- ansible/galaxy/collection/concrete_artifact_manager.py +8 -11
- ansible/galaxy/dependency_resolution/dataclasses.py +14 -4
- ansible/galaxy/dependency_resolution/providers.py +1 -1
- ansible/galaxy/dependency_resolution/reporters.py +81 -0
- ansible/galaxy/role.py +4 -8
- ansible/galaxy/token.py +28 -21
- ansible/inventory/data.py +47 -57
- ansible/inventory/group.py +44 -72
- ansible/inventory/helpers.py +9 -0
- ansible/inventory/host.py +32 -54
- ansible/inventory/manager.py +78 -34
- ansible/keyword_desc.yml +1 -1
- ansible/module_utils/_internal/__init__.py +55 -0
- ansible/module_utils/_internal/_ambient_context.py +58 -0
- ansible/module_utils/_internal/_ansiballz.py +133 -0
- ansible/module_utils/_internal/_concurrent/_daemon_threading.py +1 -0
- ansible/module_utils/_internal/_dataclass_annotation_patch.py +64 -0
- ansible/module_utils/_internal/_dataclass_validation.py +217 -0
- ansible/module_utils/_internal/_datatag/__init__.py +928 -0
- ansible/module_utils/_internal/_datatag/_tags.py +38 -0
- ansible/module_utils/_internal/_debugging.py +31 -0
- ansible/module_utils/_internal/_errors.py +30 -0
- ansible/module_utils/_internal/_json/__init__.py +63 -0
- ansible/module_utils/_internal/_json/_legacy_encoder.py +26 -0
- ansible/module_utils/_internal/_json/_profiles/__init__.py +410 -0
- ansible/module_utils/_internal/_json/_profiles/_fallback_to_str.py +73 -0
- ansible/module_utils/_internal/_json/_profiles/_module_legacy_c2m.py +31 -0
- ansible/module_utils/_internal/_json/_profiles/_module_legacy_m2c.py +35 -0
- ansible/module_utils/_internal/_json/_profiles/_module_modern_c2m.py +35 -0
- ansible/module_utils/_internal/_json/_profiles/_module_modern_m2c.py +33 -0
- ansible/module_utils/_internal/_json/_profiles/_tagless.py +50 -0
- ansible/module_utils/_internal/_patches/__init__.py +66 -0
- ansible/module_utils/_internal/_patches/_dataclass_annotation_patch.py +55 -0
- ansible/module_utils/_internal/_patches/_socket_patch.py +34 -0
- ansible/module_utils/_internal/_patches/_sys_intern_patch.py +34 -0
- ansible/module_utils/_internal/_plugin_exec_context.py +49 -0
- ansible/module_utils/_internal/_testing.py +0 -0
- ansible/module_utils/_internal/_traceback.py +89 -0
- ansible/module_utils/ansible_release.py +2 -2
- ansible/module_utils/api.py +1 -2
- ansible/module_utils/basic.py +152 -120
- ansible/module_utils/common/_utils.py +24 -28
- ansible/module_utils/common/collections.py +1 -2
- ansible/module_utils/common/dict_transformations.py +2 -2
- ansible/module_utils/common/file.py +2 -2
- ansible/module_utils/common/json.py +90 -84
- ansible/module_utils/common/locale.py +2 -2
- ansible/module_utils/common/messages.py +108 -0
- ansible/module_utils/common/parameters.py +27 -24
- ansible/module_utils/common/process.py +2 -2
- ansible/module_utils/common/respawn.py +41 -19
- ansible/module_utils/common/sentinel.py +66 -0
- ansible/module_utils/common/sys_info.py +8 -8
- ansible/module_utils/common/text/converters.py +16 -37
- ansible/module_utils/common/validation.py +35 -24
- ansible/module_utils/common/warnings.py +86 -25
- ansible/module_utils/common/yaml.py +29 -3
- ansible/module_utils/compat/datetime.py +33 -21
- ansible/module_utils/compat/paramiko.py +21 -10
- ansible/module_utils/compat/typing.py +6 -5
- ansible/module_utils/connection.py +2 -2
- ansible/module_utils/csharp/Ansible.Basic.cs +14 -11
- ansible/module_utils/csharp/Ansible.Become.cs +1 -0
- ansible/module_utils/csharp/Ansible._Async.cs +517 -0
- ansible/module_utils/datatag.py +46 -0
- ansible/module_utils/distro/__init__.py +2 -2
- ansible/module_utils/facts/ansible_collector.py +4 -5
- ansible/module_utils/facts/collector.py +13 -14
- ansible/module_utils/facts/compat.py +4 -4
- ansible/module_utils/facts/default_collectors.py +1 -1
- ansible/module_utils/facts/hardware/aix.py +34 -0
- ansible/module_utils/facts/hardware/base.py +1 -1
- ansible/module_utils/facts/hardware/darwin.py +1 -3
- ansible/module_utils/facts/hardware/freebsd.py +2 -2
- ansible/module_utils/facts/hardware/linux.py +4 -4
- ansible/module_utils/facts/namespace.py +1 -1
- ansible/module_utils/facts/network/base.py +1 -1
- ansible/module_utils/facts/network/fc_wwn.py +1 -2
- ansible/module_utils/facts/network/iscsi.py +1 -2
- ansible/module_utils/facts/network/nvme.py +1 -2
- ansible/module_utils/facts/other/facter.py +1 -2
- ansible/module_utils/facts/other/ohai.py +2 -3
- ansible/module_utils/facts/system/apparmor.py +1 -2
- ansible/module_utils/facts/system/caps.py +1 -1
- ansible/module_utils/facts/system/chroot.py +1 -2
- ansible/module_utils/facts/system/cmdline.py +1 -2
- ansible/module_utils/facts/system/date_time.py +5 -3
- ansible/module_utils/facts/system/distribution.py +9 -8
- ansible/module_utils/facts/system/dns.py +1 -1
- ansible/module_utils/facts/system/env.py +1 -2
- ansible/module_utils/facts/system/fips.py +7 -20
- ansible/module_utils/facts/system/loadavg.py +1 -2
- ansible/module_utils/facts/system/local.py +1 -2
- ansible/module_utils/facts/system/lsb.py +1 -2
- ansible/module_utils/facts/system/pkg_mgr.py +1 -2
- ansible/module_utils/facts/system/platform.py +1 -2
- ansible/module_utils/facts/system/python.py +1 -2
- ansible/module_utils/facts/system/selinux.py +1 -1
- ansible/module_utils/facts/system/service_mgr.py +1 -2
- ansible/module_utils/facts/system/ssh_pub_keys.py +1 -1
- ansible/module_utils/facts/system/systemd.py +1 -1
- ansible/module_utils/facts/system/user.py +1 -2
- ansible/module_utils/facts/utils.py +3 -3
- ansible/module_utils/facts/virtual/base.py +1 -1
- ansible/module_utils/facts/virtual/sunos.py +3 -15
- ansible/module_utils/facts/virtual/sysctl.py +3 -16
- ansible/module_utils/json_utils.py +2 -2
- ansible/module_utils/parsing/convert_bool.py +1 -1
- ansible/module_utils/service.py +18 -21
- ansible/module_utils/splitter.py +7 -7
- ansible/module_utils/testing.py +31 -0
- ansible/module_utils/urls.py +60 -31
- ansible/modules/add_host.py +4 -4
- ansible/modules/apt.py +60 -46
- ansible/modules/apt_key.py +19 -12
- ansible/modules/apt_repository.py +19 -16
- ansible/modules/assemble.py +6 -6
- ansible/modules/assert.py +4 -4
- ansible/modules/async_status.py +10 -12
- ansible/modules/async_wrapper.py +8 -3
- ansible/modules/blockinfile.py +6 -7
- ansible/modules/command.py +10 -17
- ansible/modules/copy.py +57 -144
- ansible/modules/cron.py +20 -15
- ansible/modules/deb822_repository.py +8 -9
- ansible/modules/debconf.py +5 -5
- ansible/modules/debug.py +4 -4
- ansible/modules/dnf.py +8 -8
- ansible/modules/dnf5.py +39 -13
- ansible/modules/dpkg_selections.py +4 -4
- ansible/modules/expect.py +8 -10
- ansible/modules/fail.py +4 -4
- ansible/modules/fetch.py +4 -4
- ansible/modules/file.py +174 -133
- ansible/modules/find.py +19 -17
- ansible/modules/gather_facts.py +3 -3
- ansible/modules/get_url.py +59 -53
- ansible/modules/getent.py +7 -9
- ansible/modules/git.py +28 -25
- ansible/modules/group.py +6 -6
- ansible/modules/group_by.py +4 -4
- ansible/modules/hostname.py +13 -29
- ansible/modules/import_playbook.py +6 -6
- ansible/modules/import_role.py +6 -6
- ansible/modules/import_tasks.py +6 -6
- ansible/modules/include_role.py +6 -6
- ansible/modules/include_tasks.py +6 -6
- ansible/modules/include_vars.py +6 -6
- ansible/modules/iptables.py +86 -73
- ansible/modules/known_hosts.py +10 -10
- ansible/modules/lineinfile.py +5 -5
- ansible/modules/meta.py +4 -4
- ansible/modules/mount_facts.py +2 -2
- ansible/modules/package.py +4 -4
- ansible/modules/package_facts.py +22 -10
- ansible/modules/pause.py +6 -6
- ansible/modules/ping.py +6 -6
- ansible/modules/pip.py +10 -11
- ansible/modules/raw.py +4 -4
- ansible/modules/reboot.py +6 -6
- ansible/modules/replace.py +9 -13
- ansible/modules/rpm_key.py +7 -8
- ansible/modules/script.py +4 -4
- ansible/modules/service.py +7 -8
- ansible/modules/service_facts.py +87 -10
- ansible/modules/set_fact.py +5 -5
- ansible/modules/set_stats.py +4 -4
- ansible/modules/setup.py +2 -2
- ansible/modules/shell.py +6 -6
- ansible/modules/slurp.py +6 -6
- ansible/modules/stat.py +9 -23
- ansible/modules/subversion.py +15 -15
- ansible/modules/systemd.py +6 -6
- ansible/modules/systemd_service.py +6 -6
- ansible/modules/sysvinit.py +6 -6
- ansible/modules/tempfile.py +5 -6
- ansible/modules/template.py +6 -6
- ansible/modules/unarchive.py +32 -11
- ansible/modules/uri.py +33 -26
- ansible/modules/user.py +53 -34
- ansible/modules/validate_argument_spec.py +10 -7
- ansible/modules/wait_for.py +32 -27
- ansible/modules/wait_for_connection.py +6 -6
- ansible/modules/yum_repository.py +6 -6
- ansible/parsing/ajson.py +14 -32
- ansible/parsing/dataloader.py +99 -54
- ansible/parsing/mod_args.py +28 -44
- ansible/parsing/plugin_docs.py +21 -86
- ansible/parsing/quoting.py +1 -1
- ansible/parsing/splitter.py +27 -12
- ansible/parsing/utils/addresses.py +24 -24
- ansible/parsing/utils/jsonify.py +5 -1
- ansible/parsing/utils/yaml.py +32 -61
- ansible/parsing/vault/__init__.py +319 -87
- ansible/parsing/yaml/__init__.py +0 -18
- ansible/parsing/yaml/dumper.py +6 -120
- ansible/parsing/yaml/loader.py +6 -39
- ansible/parsing/yaml/objects.py +43 -335
- ansible/playbook/__init__.py +1 -1
- ansible/playbook/attribute.py +8 -3
- ansible/playbook/base.py +182 -132
- ansible/playbook/block.py +26 -24
- ansible/playbook/collectionsearch.py +1 -15
- ansible/playbook/conditional.py +3 -77
- ansible/playbook/handler.py +8 -2
- ansible/playbook/helpers.py +41 -53
- ansible/playbook/included_file.py +31 -27
- ansible/playbook/loop_control.py +2 -2
- ansible/playbook/play.py +85 -44
- ansible/playbook/play_context.py +12 -17
- ansible/playbook/playbook_include.py +14 -15
- ansible/playbook/role/__init__.py +24 -26
- ansible/playbook/role/definition.py +15 -17
- ansible/playbook/role/include.py +2 -4
- ansible/playbook/role/metadata.py +10 -11
- ansible/playbook/role_include.py +3 -3
- ansible/playbook/taggable.py +13 -8
- ansible/playbook/task.py +188 -118
- ansible/playbook/task_include.py +5 -5
- ansible/plugins/__init__.py +68 -21
- ansible/plugins/action/__init__.py +209 -176
- ansible/plugins/action/add_host.py +1 -1
- ansible/plugins/action/assemble.py +1 -1
- ansible/plugins/action/assert.py +54 -66
- ansible/plugins/action/copy.py +7 -11
- ansible/plugins/action/debug.py +37 -31
- ansible/plugins/action/dnf.py +3 -4
- ansible/plugins/action/fail.py +1 -1
- ansible/plugins/action/fetch.py +4 -5
- ansible/plugins/action/gather_facts.py +7 -6
- ansible/plugins/action/group_by.py +1 -1
- ansible/plugins/action/include_vars.py +10 -11
- ansible/plugins/action/package.py +3 -6
- ansible/plugins/action/pause.py +2 -2
- ansible/plugins/action/script.py +15 -8
- ansible/plugins/action/service.py +6 -11
- ansible/plugins/action/set_fact.py +3 -12
- ansible/plugins/action/set_stats.py +3 -8
- ansible/plugins/action/template.py +35 -59
- ansible/plugins/action/unarchive.py +1 -1
- ansible/plugins/action/validate_argument_spec.py +5 -5
- ansible/plugins/action/wait_for_connection.py +1 -1
- ansible/plugins/become/__init__.py +31 -8
- ansible/plugins/become/runas.py +71 -0
- ansible/plugins/become/su.py +13 -8
- ansible/plugins/become/sudo.py +19 -0
- ansible/plugins/cache/__init__.py +35 -44
- ansible/plugins/cache/base.py +8 -0
- ansible/plugins/cache/jsonfile.py +10 -16
- ansible/plugins/cache/memory.py +6 -12
- ansible/plugins/callback/__init__.py +284 -179
- ansible/plugins/callback/default.py +99 -92
- ansible/plugins/callback/junit.py +44 -39
- ansible/plugins/callback/minimal.py +28 -25
- ansible/plugins/callback/oneline.py +28 -21
- ansible/plugins/callback/tree.py +16 -11
- ansible/plugins/connection/__init__.py +47 -34
- ansible/plugins/connection/local.py +150 -54
- ansible/plugins/connection/paramiko_ssh.py +21 -18
- ansible/plugins/connection/psrp.py +76 -165
- ansible/plugins/connection/ssh.py +301 -78
- ansible/plugins/connection/winrm.py +58 -140
- ansible/plugins/doc_fragments/action_common_attributes.py +14 -14
- ansible/plugins/doc_fragments/action_core.py +6 -6
- ansible/plugins/doc_fragments/backup.py +2 -2
- ansible/plugins/doc_fragments/checksum_common.py +27 -0
- ansible/plugins/doc_fragments/constructed.py +6 -2
- ansible/plugins/doc_fragments/decrypt.py +2 -2
- ansible/plugins/doc_fragments/default_callback.py +2 -2
- ansible/plugins/doc_fragments/files.py +2 -2
- ansible/plugins/doc_fragments/inventory_cache.py +2 -2
- ansible/plugins/doc_fragments/result_format_callback.py +2 -2
- ansible/plugins/doc_fragments/return_common.py +2 -2
- ansible/plugins/doc_fragments/template_common.py +4 -4
- ansible/plugins/doc_fragments/url.py +17 -1
- ansible/plugins/doc_fragments/url_windows.py +2 -2
- ansible/plugins/doc_fragments/validate.py +2 -2
- ansible/plugins/doc_fragments/vars_plugin_staging.py +2 -2
- ansible/plugins/filter/__init__.py +6 -2
- ansible/plugins/filter/b64decode.yml +22 -0
- ansible/plugins/filter/b64encode.yml +22 -0
- ansible/plugins/filter/bool.yml +11 -4
- ansible/plugins/filter/core.py +225 -108
- ansible/plugins/filter/encryption.py +32 -32
- ansible/plugins/filter/flatten.yml +3 -2
- ansible/plugins/filter/human_to_bytes.yml +1 -1
- ansible/plugins/filter/mathstuff.py +30 -37
- ansible/plugins/filter/password_hash.yml +8 -0
- ansible/plugins/filter/regex_search.yml +1 -4
- ansible/plugins/filter/split.yml +1 -1
- ansible/plugins/filter/to_nice_yaml.yml +0 -4
- ansible/plugins/filter/to_yaml.yml +0 -4
- ansible/plugins/filter/unvault.yml +1 -1
- ansible/plugins/filter/urls.py +1 -1
- ansible/plugins/filter/urlsplit.py +8 -9
- ansible/plugins/filter/vault.yml +14 -9
- ansible/plugins/filter/win_basename.yml +6 -1
- ansible/plugins/filter/win_dirname.yml +5 -0
- ansible/plugins/inventory/__init__.py +97 -77
- ansible/plugins/inventory/advanced_host_list.py +7 -5
- ansible/plugins/inventory/auto.py +11 -4
- ansible/plugins/inventory/constructed.py +21 -24
- ansible/plugins/inventory/generator.py +16 -11
- ansible/plugins/inventory/host_list.py +7 -5
- ansible/plugins/inventory/ini.py +78 -44
- ansible/plugins/inventory/script.py +189 -119
- ansible/plugins/inventory/toml.py +16 -126
- ansible/plugins/inventory/yaml.py +10 -8
- ansible/plugins/list.py +3 -3
- ansible/plugins/loader.py +197 -82
- ansible/plugins/lookup/__init__.py +21 -4
- ansible/plugins/lookup/config.py +21 -35
- ansible/plugins/lookup/csvfile.py +3 -2
- ansible/plugins/lookup/dict.py +1 -6
- ansible/plugins/lookup/env.py +12 -9
- ansible/plugins/lookup/file.py +5 -8
- ansible/plugins/lookup/first_found.py +86 -55
- ansible/plugins/lookup/indexed_items.py +1 -10
- ansible/plugins/lookup/ini.py +14 -13
- ansible/plugins/lookup/items.py +1 -1
- ansible/plugins/lookup/lines.py +8 -1
- ansible/plugins/lookup/list.py +1 -1
- ansible/plugins/lookup/nested.py +2 -18
- ansible/plugins/lookup/password.py +5 -5
- ansible/plugins/lookup/pipe.py +5 -7
- ansible/plugins/lookup/sequence.py +18 -8
- ansible/plugins/lookup/subelements.py +1 -4
- ansible/plugins/lookup/template.py +42 -36
- ansible/plugins/lookup/together.py +0 -12
- ansible/plugins/lookup/unvault.py +1 -5
- ansible/plugins/lookup/url.py +2 -8
- ansible/plugins/lookup/vars.py +16 -24
- ansible/plugins/shell/__init__.py +2 -2
- ansible/plugins/shell/cmd.py +2 -2
- ansible/plugins/shell/powershell.py +39 -22
- ansible/plugins/shell/sh.py +3 -2
- ansible/plugins/strategy/__init__.py +159 -184
- ansible/plugins/strategy/debug.py +2 -2
- ansible/plugins/strategy/free.py +16 -31
- ansible/plugins/strategy/host_pinned.py +2 -2
- ansible/plugins/strategy/linear.py +41 -41
- ansible/plugins/terminal/__init__.py +4 -4
- ansible/plugins/test/__init__.py +7 -2
- ansible/plugins/test/core.py +55 -21
- ansible/plugins/test/files.py +1 -1
- ansible/plugins/test/mathstuff.py +3 -3
- ansible/plugins/test/uri.py +3 -3
- ansible/plugins/vars/host_group_vars.py +7 -14
- ansible/release.py +2 -2
- ansible/template/__init__.py +370 -944
- ansible/utils/__init__.py +0 -18
- ansible/utils/_ssh_agent.py +657 -0
- ansible/utils/collection_loader/__init__.py +52 -5
- ansible/utils/collection_loader/_collection_config.py +5 -6
- ansible/utils/collection_loader/_collection_finder.py +79 -93
- ansible/utils/collection_loader/_collection_meta.py +13 -8
- ansible/utils/display.py +433 -63
- ansible/utils/encrypt.py +27 -19
- ansible/utils/fqcn.py +2 -2
- ansible/utils/hashing.py +2 -2
- ansible/utils/helpers.py +2 -2
- ansible/utils/listify.py +8 -8
- ansible/utils/lock.py +2 -2
- ansible/utils/path.py +4 -4
- ansible/utils/plugin_docs.py +14 -13
- ansible/utils/sentinel.py +4 -62
- ansible/utils/singleton.py +2 -0
- ansible/utils/ssh_functions.py +1 -1
- ansible/utils/unsafe_proxy.py +23 -332
- ansible/utils/vars.py +51 -8
- ansible/utils/version.py +2 -2
- ansible/vars/clean.py +5 -5
- ansible/vars/hostvars.py +60 -90
- ansible/vars/manager.py +206 -282
- ansible/vars/reserved.py +8 -9
- ansible_core-2.19.0b2.dist-info/BSD-3-Clause.txt +28 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/METADATA +5 -4
- ansible_core-2.19.0b2.dist-info/RECORD +1072 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/WHEEL +1 -1
- ansible_test/_data/completion/docker.txt +7 -7
- ansible_test/_data/completion/remote.txt +6 -6
- ansible_test/_data/completion/windows.txt +1 -0
- ansible_test/_data/requirements/ansible.txt +2 -2
- ansible_test/_data/requirements/sanity.ansible-doc.txt +3 -3
- ansible_test/_data/requirements/sanity.changelog.txt +1 -1
- ansible_test/_data/requirements/sanity.import.plugin.txt +2 -2
- ansible_test/_data/requirements/sanity.pylint.txt +4 -4
- ansible_test/_data/requirements/sanity.validate-modules.txt +2 -2
- ansible_test/_data/requirements/sanity.yamllint.txt +1 -1
- ansible_test/_data/requirements/units.txt +1 -0
- ansible_test/_internal/__init__.py +1 -0
- ansible_test/_internal/ansible_util.py +2 -0
- ansible_test/_internal/become.py +1 -0
- ansible_test/_internal/bootstrap.py +1 -0
- ansible_test/_internal/cache.py +1 -0
- ansible_test/_internal/cgroup.py +1 -0
- ansible_test/_internal/ci/__init__.py +1 -0
- ansible_test/_internal/ci/azp.py +1 -0
- ansible_test/_internal/ci/local.py +1 -0
- ansible_test/_internal/classification/__init__.py +1 -0
- ansible_test/_internal/classification/common.py +1 -0
- ansible_test/_internal/classification/csharp.py +1 -0
- ansible_test/_internal/classification/powershell.py +1 -0
- ansible_test/_internal/classification/python.py +1 -0
- ansible_test/_internal/cli/__init__.py +1 -0
- ansible_test/_internal/cli/actions.py +1 -0
- ansible_test/_internal/cli/argparsing/__init__.py +1 -0
- ansible_test/_internal/cli/argparsing/actions.py +1 -0
- ansible_test/_internal/cli/argparsing/argcompletion.py +1 -0
- ansible_test/_internal/cli/argparsing/parsers.py +1 -0
- ansible_test/_internal/cli/commands/__init__.py +11 -0
- ansible_test/_internal/cli/commands/coverage/__init__.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/__init__.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/__init__.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/combine.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/expand.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/filter.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/generate.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/missing.py +1 -0
- ansible_test/_internal/cli/commands/coverage/combine.py +1 -0
- ansible_test/_internal/cli/commands/coverage/erase.py +1 -0
- ansible_test/_internal/cli/commands/coverage/html.py +1 -0
- ansible_test/_internal/cli/commands/coverage/report.py +1 -0
- ansible_test/_internal/cli/commands/coverage/xml.py +1 -0
- ansible_test/_internal/cli/commands/env.py +1 -0
- ansible_test/_internal/cli/commands/integration/__init__.py +1 -0
- ansible_test/_internal/cli/commands/integration/network.py +1 -0
- ansible_test/_internal/cli/commands/integration/posix.py +1 -0
- ansible_test/_internal/cli/commands/integration/windows.py +1 -0
- ansible_test/_internal/cli/commands/sanity.py +9 -0
- ansible_test/_internal/cli/commands/shell.py +1 -0
- ansible_test/_internal/cli/commands/units.py +1 -0
- ansible_test/_internal/cli/compat.py +1 -0
- ansible_test/_internal/cli/completers.py +1 -0
- ansible_test/_internal/cli/converters.py +1 -0
- ansible_test/_internal/cli/environments.py +1 -0
- ansible_test/_internal/cli/epilog.py +1 -0
- ansible_test/_internal/cli/parsers/__init__.py +1 -0
- ansible_test/_internal/cli/parsers/base_argument_parsers.py +1 -0
- ansible_test/_internal/cli/parsers/helpers.py +1 -0
- ansible_test/_internal/cli/parsers/host_config_parsers.py +1 -0
- ansible_test/_internal/cli/parsers/key_value_parsers.py +1 -0
- ansible_test/_internal/cli/parsers/value_parsers.py +1 -0
- ansible_test/_internal/commands/__init__.py +1 -0
- ansible_test/_internal/commands/coverage/__init__.py +2 -1
- ansible_test/_internal/commands/coverage/analyze/__init__.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/__init__.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/combine.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/expand.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/filter.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/generate.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/missing.py +1 -0
- ansible_test/_internal/commands/coverage/combine.py +2 -1
- ansible_test/_internal/commands/coverage/erase.py +1 -0
- ansible_test/_internal/commands/coverage/html.py +1 -0
- ansible_test/_internal/commands/coverage/report.py +1 -0
- ansible_test/_internal/commands/coverage/xml.py +1 -0
- ansible_test/_internal/commands/env/__init__.py +2 -0
- ansible_test/_internal/commands/integration/__init__.py +4 -0
- ansible_test/_internal/commands/integration/cloud/__init__.py +1 -0
- ansible_test/_internal/commands/integration/cloud/acme.py +2 -1
- ansible_test/_internal/commands/integration/cloud/aws.py +1 -0
- ansible_test/_internal/commands/integration/cloud/azure.py +1 -0
- ansible_test/_internal/commands/integration/cloud/cs.py +1 -0
- ansible_test/_internal/commands/integration/cloud/digitalocean.py +1 -0
- ansible_test/_internal/commands/integration/cloud/galaxy.py +3 -2
- ansible_test/_internal/commands/integration/cloud/hcloud.py +1 -0
- ansible_test/_internal/commands/integration/cloud/httptester.py +2 -1
- ansible_test/_internal/commands/integration/cloud/nios.py +2 -1
- ansible_test/_internal/commands/integration/cloud/opennebula.py +1 -0
- ansible_test/_internal/commands/integration/cloud/openshift.py +1 -0
- ansible_test/_internal/commands/integration/cloud/scaleway.py +1 -0
- ansible_test/_internal/commands/integration/cloud/vcenter.py +1 -0
- ansible_test/_internal/commands/integration/cloud/vultr.py +1 -0
- ansible_test/_internal/commands/integration/coverage.py +1 -0
- ansible_test/_internal/commands/integration/filters.py +1 -0
- ansible_test/_internal/commands/integration/network.py +1 -0
- ansible_test/_internal/commands/integration/posix.py +1 -0
- ansible_test/_internal/commands/integration/windows.py +1 -0
- ansible_test/_internal/commands/sanity/__init__.py +16 -1
- ansible_test/_internal/commands/sanity/ansible_doc.py +1 -0
- ansible_test/_internal/commands/sanity/bin_symlinks.py +1 -0
- ansible_test/_internal/commands/sanity/compile.py +1 -0
- ansible_test/_internal/commands/sanity/ignores.py +1 -0
- ansible_test/_internal/commands/sanity/import.py +1 -0
- ansible_test/_internal/commands/sanity/integration_aliases.py +1 -0
- ansible_test/_internal/commands/sanity/pep8.py +1 -0
- ansible_test/_internal/commands/sanity/pslint.py +1 -0
- ansible_test/_internal/commands/sanity/pylint.py +24 -26
- ansible_test/_internal/commands/sanity/shellcheck.py +1 -0
- ansible_test/_internal/commands/sanity/validate_modules.py +1 -0
- ansible_test/_internal/commands/sanity/yamllint.py +1 -0
- ansible_test/_internal/commands/shell/__init__.py +1 -0
- ansible_test/_internal/commands/units/__init__.py +1 -0
- ansible_test/_internal/compat/__init__.py +1 -0
- ansible_test/_internal/compat/packaging.py +1 -0
- ansible_test/_internal/compat/yaml.py +1 -0
- ansible_test/_internal/completion.py +1 -0
- ansible_test/_internal/config.py +2 -0
- ansible_test/_internal/connections.py +1 -0
- ansible_test/_internal/constants.py +1 -0
- ansible_test/_internal/containers.py +1 -0
- ansible_test/_internal/content_config.py +1 -0
- ansible_test/_internal/core_ci.py +1 -0
- ansible_test/_internal/coverage_util.py +11 -10
- ansible_test/_internal/data.py +1 -0
- ansible_test/_internal/delegation.py +1 -0
- ansible_test/_internal/dev/__init__.py +1 -0
- ansible_test/_internal/dev/container_probe.py +1 -0
- ansible_test/_internal/diff.py +3 -2
- ansible_test/_internal/docker_util.py +2 -1
- ansible_test/_internal/encoding.py +1 -0
- ansible_test/_internal/executor.py +1 -0
- ansible_test/_internal/git.py +1 -0
- ansible_test/_internal/host_configs.py +1 -0
- ansible_test/_internal/host_profiles.py +1 -0
- ansible_test/_internal/http.py +1 -0
- ansible_test/_internal/init.py +1 -0
- ansible_test/_internal/inventory.py +35 -3
- ansible_test/_internal/io.py +1 -0
- ansible_test/_internal/metadata.py +1 -0
- ansible_test/_internal/payload.py +1 -0
- ansible_test/_internal/provider/__init__.py +1 -0
- ansible_test/_internal/provider/layout/__init__.py +1 -0
- ansible_test/_internal/provider/layout/ansible.py +1 -0
- ansible_test/_internal/provider/layout/collection.py +1 -0
- ansible_test/_internal/provider/layout/unsupported.py +1 -0
- ansible_test/_internal/provider/source/__init__.py +1 -0
- ansible_test/_internal/provider/source/git.py +1 -0
- ansible_test/_internal/provider/source/installed.py +1 -0
- ansible_test/_internal/provider/source/unsupported.py +1 -0
- ansible_test/_internal/provider/source/unversioned.py +1 -0
- ansible_test/_internal/provisioning.py +1 -0
- ansible_test/_internal/pypi_proxy.py +6 -5
- ansible_test/_internal/python_requirements.py +1 -0
- ansible_test/_internal/ssh.py +1 -0
- ansible_test/_internal/target.py +1 -0
- ansible_test/_internal/test.py +3 -2
- ansible_test/_internal/thread.py +1 -0
- ansible_test/_internal/timeout.py +1 -0
- ansible_test/_internal/util.py +1 -0
- ansible_test/_internal/util_common.py +5 -2
- ansible_test/_internal/venv.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/action-plugin-docs.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/changelog/sphinx.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/changelog.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/empty-init.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/line-endings.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-assert.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-get-exception.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-illegal-filenames.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-smart-quotes.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/replace-urlopen.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/runtime-metadata.py +28 -1
- ansible_test/_util/controller/sanity/code-smell/shebang.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/symlinks.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/use-argspec-type-path.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/use-compat-six.py +1 -0
- ansible_test/_util/controller/sanity/integration-aliases/yaml_to_json.py +2 -1
- ansible_test/_util/controller/sanity/pep8/current-ignore.txt +4 -0
- ansible_test/_util/controller/sanity/pylint/config/ansible-test-target.cfg +7 -5
- ansible_test/_util/controller/sanity/pylint/config/ansible-test.cfg +7 -5
- ansible_test/_util/controller/sanity/pylint/config/code-smell.cfg +7 -5
- ansible_test/_util/controller/sanity/pylint/config/collection.cfg +3 -5
- ansible_test/_util/controller/sanity/pylint/config/default.cfg +7 -7
- ansible_test/_util/controller/sanity/pylint/plugins/deprecated.py +1 -13
- ansible_test/_util/controller/sanity/pylint/plugins/hide_unraisable.py +1 -0
- ansible_test/_util/controller/sanity/pylint/plugins/string_format.py +1 -8
- ansible_test/_util/controller/sanity/pylint/plugins/unwanted.py +1 -8
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py +55 -28
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/module_args.py +12 -5
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/schema.py +13 -2
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/utils.py +1 -0
- ansible_test/_util/controller/sanity/yamllint/yamllinter.py +35 -17
- ansible_test/_util/controller/tools/collection_detail.py +1 -0
- ansible_test/_util/controller/tools/yaml_to_json.py +2 -1
- ansible_test/_util/target/pytest/plugins/ansible_forked.py +6 -1
- ansible_test/_util/target/pytest/plugins/ansible_pytest_collections.py +2 -1
- ansible_test/_util/target/pytest/plugins/ansible_pytest_coverage.py +1 -0
- ansible_test/_util/target/sanity/compile/compile.py +1 -0
- ansible_test/_util/target/sanity/import/importer.py +15 -16
- ansible_test/_util/target/setup/bootstrap.sh +9 -20
- ansible_test/_util/target/setup/probe_cgroups.py +1 -0
- ansible_test/_util/target/setup/quiet_pip.py +1 -0
- ansible_test/_util/target/setup/requirements.py +35 -27
- ansible_test/_util/target/tools/virtualenvcheck.py +2 -1
- ansible_test/_util/target/tools/yamlcheck.py +2 -1
- ansible/compat/selectors.py +0 -32
- ansible/errors/yaml_strings.py +0 -138
- ansible/executor/action_write_locks.py +0 -44
- ansible/executor/discovery/python_target.py +0 -47
- ansible/executor/powershell/module_powershell_wrapper.ps1 +0 -86
- ansible/executor/powershell/module_script_wrapper.ps1 +0 -22
- ansible/module_utils/compat/importlib.py +0 -26
- ansible/module_utils/compat/selectors.py +0 -32
- ansible/module_utils/pycompat24.py +0 -73
- ansible/parsing/yaml/constructor.py +0 -178
- ansible/template/native_helpers.py +0 -251
- ansible/template/template.py +0 -43
- ansible/template/vars.py +0 -77
- ansible/utils/native_jinja.py +0 -11
- ansible/vars/fact_cache.py +0 -71
- ansible_core-2.18.5rc1.dist-info/RECORD +0 -992
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/Apache-License.txt +0 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/COPYING +0 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/MIT-license.txt +0 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/PSF-license.txt +0 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/entry_points.txt +0 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/simplified_bsd.txt +0 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/top_level.txt +0 -0
ansible/executor/task_result.py
CHANGED
@@ -4,13 +4,24 @@
|
|
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.common import messages as _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'}
|
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 = (
|
@@ -21,61 +32,120 @@ CLEAN_EXCEPTIONS = (
|
|
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 [])
|
101
|
+
|
102
|
+
@property
|
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 []
|
114
|
+
|
115
|
+
return results
|
44
116
|
|
45
117
|
@property
|
46
|
-
def task_name(self):
|
47
|
-
return self.
|
118
|
+
def task_name(self) -> str:
|
119
|
+
return str(self.task_fields.get('name', '')) or self.task.get_name()
|
48
120
|
|
49
|
-
def is_changed(self):
|
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,97 @@ 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
|
+
# DTFIX-RELEASE: find a better home for this since it's public API
|
234
|
+
|
235
|
+
@property
|
236
|
+
def _result(self) -> _c.MutableMapping[str, t.Any]:
|
237
|
+
"""Use the `result` property when supporting only ansible-core 2.19 or later."""
|
238
|
+
# deprecated: description='Deprecate `_result` in favor of `result`' core_version='2.23'
|
239
|
+
return self.result
|
240
|
+
|
241
|
+
@functools.cached_property
|
242
|
+
def result(self) -> _c.MutableMapping[str, t.Any]:
|
243
|
+
"""
|
244
|
+
Returns a cached copy of the task result dictionary for consumption by callbacks.
|
245
|
+
Internal custom types are transformed to native Python types to facilitate access and serialization.
|
246
|
+
"""
|
247
|
+
return t.cast(_c.MutableMapping[str, t.Any], _vars.transform_to_native_types(self._return_data))
|
248
|
+
|
249
|
+
|
250
|
+
TaskResult = CallbackTaskResult
|
251
|
+
"""Compatibility name for the pre-2.19 callback-shaped TaskResult passed to callbacks."""
|
252
|
+
|
253
|
+
|
254
|
+
def censor_result(result: _c.Mapping[str, t.Any]) -> dict[str, t.Any]:
|
255
|
+
censored_result = {key: value for key in _PRESERVE if (value := result.get(key, ...)) is not ...}
|
256
|
+
censored_result.update(censored="the output has been hidden due to the fact that 'no_log: true' was specified for this result")
|
152
257
|
|
153
|
-
|
258
|
+
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
|
@@ -408,11 +408,8 @@ class GalaxyAPI:
|
|
408
408
|
method=method, timeout=self._server_timeout, http_agent=user_agent(), follow_redirects='safe')
|
409
409
|
except HTTPError as e:
|
410
410
|
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
|
-
)
|
411
|
+
except Exception as ex:
|
412
|
+
raise AnsibleError(f"Unknown error when attempting to call Galaxy at {url!r}.") from ex
|
416
413
|
|
417
414
|
resp_data = to_text(resp.read(), errors='surrogate_or_strict')
|
418
415
|
try:
|
@@ -471,8 +468,8 @@ class GalaxyAPI:
|
|
471
468
|
resp = open_url(url, data=args, validate_certs=self.validate_certs, method="POST", http_agent=user_agent(), timeout=self._server_timeout)
|
472
469
|
except HTTPError as e:
|
473
470
|
raise GalaxyError(e, 'Attempting to authenticate to galaxy')
|
474
|
-
except Exception as
|
475
|
-
raise AnsibleError('Unable to authenticate to galaxy
|
471
|
+
except Exception as ex:
|
472
|
+
raise AnsibleError('Unable to authenticate to galaxy.') from ex
|
476
473
|
|
477
474
|
data = json.loads(to_text(resp.read(), errors='surrogate_or_strict'))
|
478
475
|
return data
|
@@ -817,8 +814,17 @@ class GalaxyAPI:
|
|
817
814
|
|
818
815
|
signatures = data.get('signatures') or []
|
819
816
|
|
817
|
+
download_url_info = urlparse(data['download_url'])
|
818
|
+
if not download_url_info.scheme and not download_url_info.path.startswith('/'):
|
819
|
+
# galaxy does a lot of redirects, with much more complex pathing than we use
|
820
|
+
# within this codebase, without updating _call_galaxy to be able to return
|
821
|
+
# the final URL, we can't reliably build a relative URL.
|
822
|
+
raise AnsibleError(f'Invalid non absolute download_url: {data["download_url"]}')
|
823
|
+
|
824
|
+
download_url = urljoin(self.api_server, data['download_url'])
|
825
|
+
|
820
826
|
return CollectionVersionMetadata(data['namespace']['name'], data['collection']['name'], data['version'],
|
821
|
-
|
827
|
+
download_url, data['artifact']['sha256'],
|
822
828
|
data['metadata']['dependencies'], data['href'], signatures)
|
823
829
|
|
824
830
|
@g_connect(['v2', 'v3'])
|
@@ -896,12 +902,10 @@ class GalaxyAPI:
|
|
896
902
|
if not next_link:
|
897
903
|
break
|
898
904
|
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)
|
905
|
+
next_link_info = urlparse(next_link)
|
906
|
+
if not next_link_info.scheme and not next_link_info.path.startswith('/'):
|
907
|
+
raise AnsibleError(f'Invalid non absolute pagination link: {next_link}')
|
908
|
+
next_link = urljoin(self.api_server, next_link)
|
905
909
|
|
906
910
|
data = self._call_galaxy(to_native(next_link, errors='surrogate_or_strict'),
|
907
911
|
error_context_msg=error_context_msg, cache=True, cache_key=cache_key)
|
@@ -126,13 +126,13 @@ from ansible.galaxy.dependency_resolution.dataclasses import (
|
|
126
126
|
from ansible.galaxy.dependency_resolution.versioning import meets_requirements
|
127
127
|
from ansible.plugins.loader import get_all_plugin_loaders
|
128
128
|
from ansible.module_utils.common.file import S_IRWU_RG_RO, S_IRWXU_RXG_RXO, S_IXANY
|
129
|
+
from ansible.module_utils.common.sentinel import Sentinel
|
129
130
|
from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text
|
130
131
|
from ansible.module_utils.common.collections import is_sequence
|
131
132
|
from ansible.module_utils.common.yaml import yaml_dump
|
132
133
|
from ansible.utils.collection_loader import AnsibleCollectionRef
|
133
134
|
from ansible.utils.display import Display
|
134
135
|
from ansible.utils.hashing import secure_hash, secure_hash_s
|
135
|
-
from ansible.utils.sentinel import Sentinel
|
136
136
|
|
137
137
|
|
138
138
|
display = Display()
|
@@ -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
|
|
@@ -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)
|
@@ -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
|
@@ -39,7 +39,7 @@ except ImportError:
|
|
39
39
|
|
40
40
|
# TODO: add python requirements to ansible-test's ansible-core distribution info and remove the hardcoded lowerbound/upperbound fallback
|
41
41
|
RESOLVELIB_LOWERBOUND = SemanticVersion("0.5.3")
|
42
|
-
RESOLVELIB_UPPERBOUND = SemanticVersion("
|
42
|
+
RESOLVELIB_UPPERBOUND = SemanticVersion("2.0.0")
|
43
43
|
RESOLVELIB_VERSION = SemanticVersion.from_loose_version(LooseVersion(resolvelib_version))
|
44
44
|
|
45
45
|
|
@@ -5,12 +5,46 @@
|
|
5
5
|
|
6
6
|
from __future__ import annotations
|
7
7
|
|
8
|
+
from collections import defaultdict
|
9
|
+
|
8
10
|
try:
|
9
11
|
from resolvelib import BaseReporter
|
10
12
|
except ImportError:
|
11
13
|
class BaseReporter: # type: ignore[no-redef]
|
12
14
|
pass
|
13
15
|
|
16
|
+
try:
|
17
|
+
from resolvelib.resolvers import Criterion
|
18
|
+
except ImportError:
|
19
|
+
class Criterion: # type: ignore[no-redef]
|
20
|
+
pass
|
21
|
+
|
22
|
+
from ansible.utils.display import Display
|
23
|
+
from .dataclasses import Candidate, Requirement
|
24
|
+
|
25
|
+
|
26
|
+
display = Display()
|
27
|
+
|
28
|
+
|
29
|
+
_CLI_APP_NAME = 'ansible-galaxy'
|
30
|
+
_MESSAGES_AT_REJECT_COUNT = {
|
31
|
+
1: (
|
32
|
+
f'{_CLI_APP_NAME} is looking at multiple versions of {{fqcn}} to '
|
33
|
+
'determine which version is compatible with other '
|
34
|
+
'requirements. This could take a while.'
|
35
|
+
),
|
36
|
+
8: (
|
37
|
+
f'{_CLI_APP_NAME} is looking at multiple versions of {{fqcn}} to '
|
38
|
+
'determine which version is compatible with other '
|
39
|
+
'requirements. This could take a while.'
|
40
|
+
),
|
41
|
+
13: (
|
42
|
+
'This is taking longer than usual. You might need to provide '
|
43
|
+
'the dependency resolver with stricter constraints to reduce '
|
44
|
+
'runtime. If you want to abort this run, press Ctrl + C.'
|
45
|
+
),
|
46
|
+
}
|
47
|
+
|
14
48
|
|
15
49
|
class CollectionDependencyReporter(BaseReporter):
|
16
50
|
"""A dependency reporter for Ansible Collections.
|
@@ -18,3 +52,50 @@ class CollectionDependencyReporter(BaseReporter):
|
|
18
52
|
This is a proxy class allowing us to abstract away importing resolvelib
|
19
53
|
outside of the `ansible.galaxy.dependency_resolution` Python package.
|
20
54
|
"""
|
55
|
+
|
56
|
+
def __init__(self) -> None:
|
57
|
+
"""Initialize the collection rejection counter."""
|
58
|
+
super().__init__()
|
59
|
+
|
60
|
+
self.reject_count_by_fqcn: defaultdict[str, int] = defaultdict(int)
|
61
|
+
|
62
|
+
def _maybe_log_rejection_message(self, candidate: Candidate) -> bool:
|
63
|
+
"""Print out rejection messages on pre-defined limit hits."""
|
64
|
+
# Inspired by https://github.com/pypa/pip/commit/9731131
|
65
|
+
self.reject_count_by_fqcn[candidate.fqcn] += 1
|
66
|
+
|
67
|
+
collection_rejections_count = self.reject_count_by_fqcn[candidate.fqcn]
|
68
|
+
|
69
|
+
if collection_rejections_count not in _MESSAGES_AT_REJECT_COUNT:
|
70
|
+
return False
|
71
|
+
|
72
|
+
collection_rejection_message = _MESSAGES_AT_REJECT_COUNT[
|
73
|
+
collection_rejections_count
|
74
|
+
]
|
75
|
+
display.display(collection_rejection_message.format(fqcn=candidate.fqcn))
|
76
|
+
|
77
|
+
return True
|
78
|
+
|
79
|
+
def rejecting_candidate( # resolvelib >= 0.9.0
|
80
|
+
self,
|
81
|
+
criterion: Criterion[Candidate, Requirement],
|
82
|
+
candidate: Candidate,
|
83
|
+
) -> None:
|
84
|
+
"""Augment rejection messages with conflict details."""
|
85
|
+
if not self._maybe_log_rejection_message(candidate):
|
86
|
+
return
|
87
|
+
|
88
|
+
msg = 'Will try a different candidate, due to conflict:'
|
89
|
+
for req_info in criterion.information:
|
90
|
+
req, parent = req_info.requirement, req_info.parent
|
91
|
+
msg += '\n '
|
92
|
+
if parent:
|
93
|
+
msg += f'{parent !s} depends on '
|
94
|
+
else:
|
95
|
+
msg += 'The user requested '
|
96
|
+
msg += str(req)
|
97
|
+
display.v(msg)
|
98
|
+
|
99
|
+
def backtracking(self, candidate: Candidate) -> None: # resolvelib < 0.9.0
|
100
|
+
"""Print out rejection messages on pre-defined limit hits."""
|
101
|
+
self._maybe_log_rejection_message(candidate)
|
ansible/galaxy/role.py
CHANGED
@@ -185,13 +185,11 @@ class GalaxyRole(object):
|
|
185
185
|
info_path = os.path.join(self.path, self.META_INSTALL)
|
186
186
|
if os.path.isfile(info_path):
|
187
187
|
try:
|
188
|
-
|
189
|
-
|
188
|
+
with open(info_path, 'r') as f:
|
189
|
+
self._install_info = yaml_load(f)
|
190
190
|
except Exception:
|
191
191
|
display.vvvvv("Unable to load Galaxy install info for %s" % self.name)
|
192
192
|
return False
|
193
|
-
finally:
|
194
|
-
f.close()
|
195
193
|
return self._install_info
|
196
194
|
|
197
195
|
@property
|
@@ -470,12 +468,10 @@ class GalaxyRole(object):
|
|
470
468
|
meta_path = os.path.join(self.path, meta_requirements)
|
471
469
|
if os.path.isfile(meta_path):
|
472
470
|
try:
|
473
|
-
|
474
|
-
|
471
|
+
with open(meta_path, 'r') as f:
|
472
|
+
self._requirements = yaml_load(f)
|
475
473
|
except Exception:
|
476
474
|
display.vvvvv("Unable to load requirements for %s" % self.name)
|
477
|
-
finally:
|
478
|
-
f.close()
|
479
475
|
|
480
476
|
break
|
481
477
|
|