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/_internal/ansible_collections/ansible/_protomatter/plugins/filter/python_literal_eval.py
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import ast
|
4
|
+
|
5
|
+
from ansible.errors import AnsibleTypeError
|
6
|
+
|
7
|
+
|
8
|
+
def python_literal_eval(value: object, ignore_errors=False) -> object:
|
9
|
+
try:
|
10
|
+
if isinstance(value, str):
|
11
|
+
return ast.literal_eval(value)
|
12
|
+
|
13
|
+
raise AnsibleTypeError("The `value` to eval must be a string.", obj=value)
|
14
|
+
except Exception:
|
15
|
+
if ignore_errors:
|
16
|
+
return value
|
17
|
+
|
18
|
+
raise
|
19
|
+
|
20
|
+
|
21
|
+
class FilterModule(object):
|
22
|
+
@staticmethod
|
23
|
+
def filters():
|
24
|
+
return dict(python_literal_eval=python_literal_eval)
|
ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/python_literal_eval.yml
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
DOCUMENTATION:
|
2
|
+
name: python_literal_eval
|
3
|
+
version_added: "2.19"
|
4
|
+
short_description: evaluate a Python literal expression string
|
5
|
+
description:
|
6
|
+
- Evaluates the input string as a Python literal expression, returning the resulting data structure.
|
7
|
+
- Previous versions of Ansible applied this behavior to all template results in non-native Jinja mode.
|
8
|
+
- This filter provides a way to emulate the previous behavior.
|
9
|
+
notes:
|
10
|
+
- Directly calls Python's C(ast.literal_eval).
|
11
|
+
positional: _input
|
12
|
+
options:
|
13
|
+
_input:
|
14
|
+
description: Python literal string expression.
|
15
|
+
type: str
|
16
|
+
required: true
|
17
|
+
ignore_errors:
|
18
|
+
description: Whether to silently ignore all errors resulting from the literal_eval operation. If true, the input is silently returned unmodified when an error occurs.
|
19
|
+
type: bool
|
20
|
+
default: false
|
21
|
+
|
22
|
+
EXAMPLES: |
|
23
|
+
- name: evaluate an expression comprised only of Python literals
|
24
|
+
assert:
|
25
|
+
that: (another_var | ansible._protomatter.python_literal_eval)[1] == 2 # in 2.19 and later, the explicit python_literal_eval emulates the old templating behavior
|
26
|
+
vars:
|
27
|
+
another_var: "{{ some_var }}" # in 2.18 and earlier, indirection through templating caused implicit literal_eval, converting the value to a list
|
28
|
+
some_var: "[1, 2]" # a value that looks like a Python list literal embedded in a string
|
29
|
+
|
30
|
+
RETURN:
|
31
|
+
_value:
|
32
|
+
description: Resulting data structure.
|
33
|
+
type: raw
|
@@ -0,0 +1,16 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import typing as t
|
4
|
+
|
5
|
+
from ansible.module_utils._internal._datatag import AnsibleTagHelper
|
6
|
+
|
7
|
+
|
8
|
+
def tag_names(value: object) -> list[str]:
|
9
|
+
"""Return a list of tag type names (if any) present on the given object."""
|
10
|
+
return sorted(tag_type.__name__ for tag_type in AnsibleTagHelper.tag_types(value))
|
11
|
+
|
12
|
+
|
13
|
+
class FilterModule:
|
14
|
+
@staticmethod
|
15
|
+
def filters() -> dict[str, t.Callable]:
|
16
|
+
return dict(tag_names=tag_names)
|
@@ -0,0 +1,17 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import typing as t
|
4
|
+
|
5
|
+
from ansible.plugins import accept_args_markers
|
6
|
+
|
7
|
+
|
8
|
+
@accept_args_markers
|
9
|
+
def true_type(obj: object) -> str:
|
10
|
+
"""Internal filter to show the true type name of the given object, not just the base type name like the `debug` filter."""
|
11
|
+
return obj.__class__.__name__
|
12
|
+
|
13
|
+
|
14
|
+
class FilterModule(object):
|
15
|
+
@staticmethod
|
16
|
+
def filters() -> dict[str, t.Callable]:
|
17
|
+
return dict(true_type=true_type)
|
@@ -0,0 +1,49 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import copy
|
4
|
+
import dataclasses
|
5
|
+
import typing as t
|
6
|
+
|
7
|
+
from ansible._internal._templating._jinja_common import validate_arg_type
|
8
|
+
from ansible._internal._templating._lazy_containers import _AnsibleLazyTemplateMixin
|
9
|
+
from ansible._internal._templating._transform import _type_transform_mapping
|
10
|
+
from ansible.errors import AnsibleError
|
11
|
+
|
12
|
+
|
13
|
+
def unmask(value: object, type_names: str | list[str]) -> object:
|
14
|
+
"""
|
15
|
+
Internal filter to suppress automatic type transformation in Jinja (e.g., WarningMessageDetail, DeprecationMessageDetail, ErrorDetail).
|
16
|
+
Lazy collection caching is in play - the first attempt to access a value in a given lazy container must be with unmasking in place, or the transformed value
|
17
|
+
will already be cached.
|
18
|
+
"""
|
19
|
+
validate_arg_type("type_names", type_names, (str, list))
|
20
|
+
|
21
|
+
if isinstance(type_names, str):
|
22
|
+
check_type_names = [type_names]
|
23
|
+
else:
|
24
|
+
check_type_names = type_names
|
25
|
+
|
26
|
+
valid_type_names = {key.__name__ for key in _type_transform_mapping}
|
27
|
+
invalid_type_names = [type_name for type_name in check_type_names if type_name not in valid_type_names]
|
28
|
+
|
29
|
+
if invalid_type_names:
|
30
|
+
raise AnsibleError(f'Unknown type name(s): {", ".join(invalid_type_names)}', obj=type_names)
|
31
|
+
|
32
|
+
result: object
|
33
|
+
|
34
|
+
if isinstance(value, _AnsibleLazyTemplateMixin):
|
35
|
+
result = copy.copy(value)
|
36
|
+
result._lazy_options = dataclasses.replace(
|
37
|
+
result._lazy_options,
|
38
|
+
unmask_type_names=result._lazy_options.unmask_type_names | frozenset(check_type_names),
|
39
|
+
)
|
40
|
+
else:
|
41
|
+
result = value
|
42
|
+
|
43
|
+
return result
|
44
|
+
|
45
|
+
|
46
|
+
class FilterModule(object):
|
47
|
+
@staticmethod
|
48
|
+
def filters() -> dict[str, t.Callable]:
|
49
|
+
return dict(unmask=unmask)
|
@@ -0,0 +1,21 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from ansible.plugins.lookup import LookupBase
|
4
|
+
|
5
|
+
|
6
|
+
class LookupModule(LookupBase):
|
7
|
+
"""Specialized config lookup that applies data transformations on values that config cannot."""
|
8
|
+
|
9
|
+
def run(self, terms, variables=None, **kwargs):
|
10
|
+
if not terms or not (config_name := terms[0]):
|
11
|
+
raise ValueError("config name is required")
|
12
|
+
|
13
|
+
match config_name:
|
14
|
+
case 'DISPLAY_TRACEBACK':
|
15
|
+
# since config can't expand this yet, we need the post-processed version
|
16
|
+
from ansible.module_utils._internal._traceback import traceback_for
|
17
|
+
|
18
|
+
return traceback_for()
|
19
|
+
# DTFIX-FUTURE: plumb through normal config fallback
|
20
|
+
case _:
|
21
|
+
raise ValueError(f"Unknown config name {config_name!r}.")
|
@@ -0,0 +1,15 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import typing as t
|
4
|
+
|
5
|
+
from ansible.module_utils._internal import _datatag
|
6
|
+
|
7
|
+
|
8
|
+
def tagged(value: t.Any) -> bool:
|
9
|
+
return bool(_datatag.AnsibleTagHelper.tag_types(value))
|
10
|
+
|
11
|
+
|
12
|
+
class TestModule:
|
13
|
+
@staticmethod
|
14
|
+
def tests() -> dict[str, t.Callable]:
|
15
|
+
return dict(tagged=tagged)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
DOCUMENTATION:
|
2
|
+
name: tagged
|
3
|
+
author: Ansible Core
|
4
|
+
version_added: "2.19"
|
5
|
+
short_description: does the value have a data tag
|
6
|
+
description:
|
7
|
+
- Check if the provided value has a data tag.
|
8
|
+
options:
|
9
|
+
_input:
|
10
|
+
description: A value.
|
11
|
+
type: raw
|
12
|
+
|
13
|
+
EXAMPLES: |
|
14
|
+
is_data_tagged: "{{ my_variable is ansible._protomatter.tagged }}"
|
15
|
+
|
16
|
+
RETURN:
|
17
|
+
_value:
|
18
|
+
description: Returns C(True) if the value has one or more data tags, otherwise C(False).
|
19
|
+
type: boolean
|
@@ -0,0 +1,18 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import typing as t
|
4
|
+
|
5
|
+
from ansible.module_utils._internal import _datatag
|
6
|
+
|
7
|
+
|
8
|
+
def tagged_with(value: t.Any, tag_name: str) -> bool:
|
9
|
+
if tag_type := _datatag._known_tag_type_map.get(tag_name):
|
10
|
+
return tag_type.is_tagged_on(value)
|
11
|
+
|
12
|
+
raise ValueError(f"Unknown tag name {tag_name!r}.")
|
13
|
+
|
14
|
+
|
15
|
+
class TestModule:
|
16
|
+
@staticmethod
|
17
|
+
def tests() -> dict[str, t.Callable]:
|
18
|
+
return dict(tagged_with=tagged_with)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
DOCUMENTATION:
|
2
|
+
name: tagged_with
|
3
|
+
author: Ansible Core
|
4
|
+
version_added: "2.19"
|
5
|
+
short_description: does the value have the specified data tag
|
6
|
+
description:
|
7
|
+
- Check if the provided value has the specified data tag.
|
8
|
+
options:
|
9
|
+
_input:
|
10
|
+
description: A value.
|
11
|
+
type: raw
|
12
|
+
|
13
|
+
EXAMPLES: |
|
14
|
+
is_data_tagged: "{{ my_variable is ansible._protomatter.tagged_with('Origin') }}"
|
15
|
+
|
16
|
+
RETURN:
|
17
|
+
_value:
|
18
|
+
description: Returns C(True) if the value has the specified data tag, otherwise C(False).
|
19
|
+
type: boolean
|
ansible/cli/__init__.py
CHANGED
@@ -7,8 +7,22 @@ from __future__ import annotations
|
|
7
7
|
|
8
8
|
import locale
|
9
9
|
import os
|
10
|
+
import signal
|
10
11
|
import sys
|
11
12
|
|
13
|
+
|
14
|
+
# We overload the ``ansible`` adhoc command to provide the functionality for
|
15
|
+
# ``SSH_ASKPASS``. This code is here, and not in ``adhoc.py`` to bypass
|
16
|
+
# unnecessary code. The program provided to ``SSH_ASKPASS`` can only be invoked
|
17
|
+
# as a singular command, ``python -m`` doesn't work for that use case, and we
|
18
|
+
# aren't adding a new entrypoint at this time. Assume that if we are executing
|
19
|
+
# and there is only a single item in argv plus the executable, and the env var
|
20
|
+
# is set we are in ``SSH_ASKPASS`` mode
|
21
|
+
if 1 <= len(sys.argv) <= 2 and os.path.basename(sys.argv[0]) == "ansible" and os.getenv('_ANSIBLE_SSH_ASKPASS_SHM'):
|
22
|
+
from ansible.cli import _ssh_askpass
|
23
|
+
_ssh_askpass.main()
|
24
|
+
|
25
|
+
|
12
26
|
# Used for determining if the system is running a new enough python version
|
13
27
|
# and should only restrict on our documented minimum versions
|
14
28
|
if sys.version_info < (3, 11):
|
@@ -63,18 +77,7 @@ def initialize_locale():
|
|
63
77
|
initialize_locale()
|
64
78
|
|
65
79
|
|
66
|
-
|
67
|
-
from ansible.module_utils.compat.version import LooseVersion
|
68
|
-
|
69
|
-
# Used for determining if the system is running a new enough Jinja2 version
|
70
|
-
# and should only restrict on our documented minimum versions
|
71
|
-
jinja2_version = version('jinja2')
|
72
|
-
if jinja2_version < LooseVersion('3.0'):
|
73
|
-
raise SystemExit(
|
74
|
-
'ERROR: Ansible requires Jinja2 3.0 or newer on the controller. '
|
75
|
-
'Current version: %s' % jinja2_version
|
76
|
-
)
|
77
|
-
|
80
|
+
import atexit
|
78
81
|
import errno
|
79
82
|
import getpass
|
80
83
|
import subprocess
|
@@ -82,30 +85,42 @@ import traceback
|
|
82
85
|
from abc import ABC, abstractmethod
|
83
86
|
from pathlib import Path
|
84
87
|
|
88
|
+
from ansible import _internal # do not remove or defer; ensures controller-specific state is set early
|
89
|
+
|
90
|
+
_internal.setup()
|
91
|
+
|
92
|
+
from ansible.errors import AnsibleError, ExitCode
|
93
|
+
|
85
94
|
try:
|
86
95
|
from ansible import constants as C
|
87
96
|
from ansible.utils.display import Display
|
88
97
|
display = Display()
|
89
|
-
except Exception as
|
90
|
-
|
98
|
+
except Exception as ex:
|
99
|
+
if isinstance(ex, AnsibleError):
|
100
|
+
ex_msg = ' '.join((ex.message, ex._help_text)).strip()
|
101
|
+
else:
|
102
|
+
ex_msg = str(ex)
|
103
|
+
|
104
|
+
print(f'ERROR: {ex_msg}\n\n{"".join(traceback.format_exception(ex))}', file=sys.stderr)
|
91
105
|
sys.exit(5)
|
92
106
|
|
107
|
+
|
93
108
|
from ansible import context
|
94
109
|
from ansible.cli.arguments import option_helpers as opt_help
|
95
|
-
from ansible.errors import AnsibleError, AnsibleOptionsError, AnsibleParserError
|
96
110
|
from ansible.inventory.manager import InventoryManager
|
97
111
|
from ansible.module_utils.six import string_types
|
98
112
|
from ansible.module_utils.common.text.converters import to_bytes, to_text
|
99
113
|
from ansible.module_utils.common.collections import is_sequence
|
100
114
|
from ansible.module_utils.common.file import is_executable
|
115
|
+
from ansible.module_utils.common.process import get_bin_path
|
101
116
|
from ansible.parsing.dataloader import DataLoader
|
102
|
-
from ansible.parsing.vault import PromptVaultSecret, get_file_vault_secret
|
117
|
+
from ansible.parsing.vault import PromptVaultSecret, get_file_vault_secret, VaultSecretsContext
|
103
118
|
from ansible.plugins.loader import add_all_plugin_dirs, init_plugin_loader
|
104
119
|
from ansible.release import __version__
|
120
|
+
from ansible.utils._ssh_agent import SshAgentClient
|
105
121
|
from ansible.utils.collection_loader import AnsibleCollectionConfig
|
106
122
|
from ansible.utils.collection_loader._collection_finder import _get_collection_name_from_path
|
107
123
|
from ansible.utils.path import unfrackpath
|
108
|
-
from ansible.utils.unsafe_proxy import to_unsafe_text
|
109
124
|
from ansible.vars.manager import VariableManager
|
110
125
|
|
111
126
|
try:
|
@@ -115,8 +130,79 @@ except ImportError:
|
|
115
130
|
HAS_ARGCOMPLETE = False
|
116
131
|
|
117
132
|
|
133
|
+
_SSH_AGENT_STDOUT_READ_TIMEOUT = 5 # seconds
|
134
|
+
|
135
|
+
|
136
|
+
def _ssh_agent_timeout_handler(signum, frame):
|
137
|
+
raise TimeoutError
|
138
|
+
|
139
|
+
|
140
|
+
def _launch_ssh_agent() -> None:
|
141
|
+
ssh_agent_cfg = C.config.get_config_value('SSH_AGENT')
|
142
|
+
match ssh_agent_cfg:
|
143
|
+
case 'none':
|
144
|
+
display.debug('SSH_AGENT set to none')
|
145
|
+
return
|
146
|
+
case 'auto':
|
147
|
+
try:
|
148
|
+
ssh_agent_bin = get_bin_path('ssh-agent')
|
149
|
+
except ValueError as e:
|
150
|
+
raise AnsibleError('SSH_AGENT set to auto, but cannot find ssh-agent binary') from e
|
151
|
+
ssh_agent_dir = os.path.join(C.DEFAULT_LOCAL_TMP, 'ssh_agent')
|
152
|
+
os.mkdir(ssh_agent_dir, 0o700)
|
153
|
+
sock = os.path.join(ssh_agent_dir, 'agent.sock')
|
154
|
+
display.vvv('SSH_AGENT: starting...')
|
155
|
+
try:
|
156
|
+
p = subprocess.Popen(
|
157
|
+
[ssh_agent_bin, '-D', '-s', '-a', sock],
|
158
|
+
stdin=subprocess.PIPE,
|
159
|
+
stdout=subprocess.PIPE,
|
160
|
+
stderr=subprocess.PIPE,
|
161
|
+
)
|
162
|
+
except OSError as e:
|
163
|
+
raise AnsibleError(
|
164
|
+
f'Could not start ssh-agent: {e}'
|
165
|
+
) from e
|
166
|
+
|
167
|
+
if p.poll() is not None:
|
168
|
+
raise AnsibleError(
|
169
|
+
f'Could not start ssh-agent: rc={p.returncode} stderr="{p.stderr.read().decode()}"'
|
170
|
+
)
|
171
|
+
|
172
|
+
old_sigalrm_handler = signal.signal(signal.SIGALRM, _ssh_agent_timeout_handler)
|
173
|
+
signal.alarm(_SSH_AGENT_STDOUT_READ_TIMEOUT)
|
174
|
+
try:
|
175
|
+
stdout = p.stdout.read(13)
|
176
|
+
except TimeoutError:
|
177
|
+
stdout = b''
|
178
|
+
finally:
|
179
|
+
signal.alarm(0)
|
180
|
+
signal.signal(signal.SIGALRM, old_sigalrm_handler)
|
181
|
+
|
182
|
+
if stdout != b'SSH_AUTH_SOCK':
|
183
|
+
display.warning(
|
184
|
+
f'The first 13 characters of stdout did not match the '
|
185
|
+
f'expected SSH_AUTH_SOCK. This may not be the right binary, '
|
186
|
+
f'or an incompatible agent: {stdout.decode()}'
|
187
|
+
)
|
188
|
+
display.vvv(f'SSH_AGENT: ssh-agent[{p.pid}] started and bound to {sock}')
|
189
|
+
atexit.register(p.terminate)
|
190
|
+
case _:
|
191
|
+
sock = ssh_agent_cfg
|
192
|
+
|
193
|
+
try:
|
194
|
+
with SshAgentClient(sock) as client:
|
195
|
+
client.list()
|
196
|
+
except Exception as e:
|
197
|
+
raise AnsibleError(
|
198
|
+
f'Could not communicate with ssh-agent using auth sock {sock}: {e}'
|
199
|
+
) from e
|
200
|
+
|
201
|
+
os.environ['SSH_AUTH_SOCK'] = os.environ['ANSIBLE_SSH_AGENT'] = sock
|
202
|
+
|
203
|
+
|
118
204
|
class CLI(ABC):
|
119
|
-
|
205
|
+
""" code behind bin/ansible* programs """
|
120
206
|
|
121
207
|
PAGER = C.config.get_config_value('PAGER')
|
122
208
|
|
@@ -124,6 +210,7 @@ class CLI(ABC):
|
|
124
210
|
# -S (chop long lines) -X (disable termcap init and de-init)
|
125
211
|
LESS_OPTS = 'FRSX'
|
126
212
|
SKIP_INVENTORY_DEFAULTS = False
|
213
|
+
USES_CONNECTION = False
|
127
214
|
|
128
215
|
def __init__(self, args, callback=None):
|
129
216
|
"""
|
@@ -137,6 +224,9 @@ class CLI(ABC):
|
|
137
224
|
self.parser = None
|
138
225
|
self.callback = callback
|
139
226
|
|
227
|
+
self.show_devel_warning()
|
228
|
+
|
229
|
+
def show_devel_warning(self) -> None:
|
140
230
|
if C.DEVEL_WARNING and __version__.endswith('dev0'):
|
141
231
|
display.warning(
|
142
232
|
'You are running the development version of Ansible. You should only run Ansible from "devel" if '
|
@@ -208,7 +298,7 @@ class CLI(ABC):
|
|
208
298
|
@staticmethod
|
209
299
|
def setup_vault_secrets(loader, vault_ids, vault_password_files=None,
|
210
300
|
ask_vault_pass=None, create_new_password=False,
|
211
|
-
auto_prompt=True):
|
301
|
+
auto_prompt=True, initialize_context=True):
|
212
302
|
# list of tuples
|
213
303
|
vault_secrets = []
|
214
304
|
|
@@ -305,24 +395,22 @@ class CLI(ABC):
|
|
305
395
|
if last_exception and not found_vault_secret:
|
306
396
|
raise last_exception
|
307
397
|
|
398
|
+
if initialize_context:
|
399
|
+
VaultSecretsContext.initialize(VaultSecretsContext(vault_secrets))
|
400
|
+
|
308
401
|
return vault_secrets
|
309
402
|
|
310
403
|
@staticmethod
|
311
|
-
def _get_secret(prompt):
|
312
|
-
|
313
|
-
secret = getpass.getpass(prompt=prompt)
|
314
|
-
if secret:
|
315
|
-
secret = to_unsafe_text(secret)
|
316
|
-
return secret
|
404
|
+
def _get_secret(prompt: str) -> str:
|
405
|
+
return getpass.getpass(prompt=prompt)
|
317
406
|
|
318
407
|
@staticmethod
|
319
408
|
def ask_passwords():
|
320
|
-
|
409
|
+
""" prompt for connection and become passwords if needed """
|
321
410
|
|
322
411
|
op = context.CLIARGS
|
323
412
|
sshpass = None
|
324
413
|
becomepass = None
|
325
|
-
become_prompt = ''
|
326
414
|
|
327
415
|
become_prompt_method = "BECOME" if C.AGNOSTIC_BECOME_PROMPT else op['become_method'].upper()
|
328
416
|
|
@@ -344,10 +432,10 @@ class CLI(ABC):
|
|
344
432
|
except EOFError:
|
345
433
|
pass
|
346
434
|
|
347
|
-
return
|
435
|
+
return sshpass, becomepass
|
348
436
|
|
349
437
|
def validate_conflicts(self, op, runas_opts=False, fork_opts=False):
|
350
|
-
|
438
|
+
""" check for conflicting options """
|
351
439
|
|
352
440
|
if fork_opts:
|
353
441
|
if op.forks < 1:
|
@@ -459,7 +547,7 @@ class CLI(ABC):
|
|
459
547
|
|
460
548
|
@staticmethod
|
461
549
|
def version_info(gitinfo=False):
|
462
|
-
|
550
|
+
""" return full ansible version info """
|
463
551
|
if gitinfo:
|
464
552
|
# expensive call, user with care
|
465
553
|
ansible_version_string = opt_help.version()
|
@@ -485,7 +573,7 @@ class CLI(ABC):
|
|
485
573
|
|
486
574
|
@staticmethod
|
487
575
|
def pager(text):
|
488
|
-
|
576
|
+
""" find reasonable way to display text """
|
489
577
|
# this is a much simpler form of what is in pydoc.py
|
490
578
|
if not sys.stdout.isatty():
|
491
579
|
display.display(text, screen_only=True)
|
@@ -504,7 +592,7 @@ class CLI(ABC):
|
|
504
592
|
|
505
593
|
@staticmethod
|
506
594
|
def pager_pipe(text):
|
507
|
-
|
595
|
+
""" pipe text through a pager """
|
508
596
|
if 'less' in CLI.PAGER:
|
509
597
|
os.environ['LESS'] = CLI.LESS_OPTS
|
510
598
|
try:
|
@@ -515,8 +603,7 @@ class CLI(ABC):
|
|
515
603
|
except KeyboardInterrupt:
|
516
604
|
pass
|
517
605
|
|
518
|
-
|
519
|
-
def _play_prereqs():
|
606
|
+
def _play_prereqs(self):
|
520
607
|
# TODO: evaluate moving all of the code that touches ``AnsibleCollectionConfig``
|
521
608
|
# into ``init_plugin_loader`` so that we can specifically remove
|
522
609
|
# ``AnsibleCollectionConfig.playbook_paths`` to make it immutable after instantiation
|
@@ -547,6 +634,12 @@ class CLI(ABC):
|
|
547
634
|
auto_prompt=False)
|
548
635
|
loader.set_vault_secrets(vault_secrets)
|
549
636
|
|
637
|
+
if self.USES_CONNECTION:
|
638
|
+
try:
|
639
|
+
_launch_ssh_agent()
|
640
|
+
except Exception as e:
|
641
|
+
raise AnsibleError('Failed to launch ssh agent', orig_exc=e)
|
642
|
+
|
550
643
|
# create the inventory, and filter it based on the subset specified (if any)
|
551
644
|
inventory = InventoryManager(loader=loader, sources=options['inventory'], cache=(not options.get('flush_cache')))
|
552
645
|
|
@@ -554,8 +647,19 @@ class CLI(ABC):
|
|
554
647
|
# the code, ensuring a consistent view of global variables
|
555
648
|
variable_manager = VariableManager(loader=loader, inventory=inventory, version_info=CLI.version_info(gitinfo=False))
|
556
649
|
|
650
|
+
# flush fact cache if requested
|
651
|
+
if options['flush_cache']:
|
652
|
+
CLI._flush_cache(inventory, variable_manager)
|
653
|
+
|
557
654
|
return loader, inventory, variable_manager
|
558
655
|
|
656
|
+
@staticmethod
|
657
|
+
def _flush_cache(inventory, variable_manager):
|
658
|
+
variable_manager.clear_facts('localhost')
|
659
|
+
for host in inventory.list_hosts():
|
660
|
+
hostname = host.get_name()
|
661
|
+
variable_manager.clear_facts(hostname)
|
662
|
+
|
559
663
|
@staticmethod
|
560
664
|
def get_host_list(inventory, subset, pattern='all'):
|
561
665
|
|
@@ -575,10 +679,9 @@ class CLI(ABC):
|
|
575
679
|
return hosts
|
576
680
|
|
577
681
|
@staticmethod
|
578
|
-
def get_password_from_file(pwd_file):
|
579
|
-
|
682
|
+
def get_password_from_file(pwd_file: str) -> str:
|
580
683
|
b_pwd_file = to_bytes(pwd_file)
|
581
|
-
|
684
|
+
|
582
685
|
if b_pwd_file == b'-':
|
583
686
|
# ensure its read as bytes
|
584
687
|
secret = sys.stdin.buffer.read()
|
@@ -598,14 +701,13 @@ class CLI(ABC):
|
|
598
701
|
|
599
702
|
stdout, stderr = p.communicate()
|
600
703
|
if p.returncode != 0:
|
601
|
-
raise AnsibleError("The password script %s returned an error (rc=%s): %s" % (pwd_file, p.returncode, stderr))
|
704
|
+
raise AnsibleError("The password script %s returned an error (rc=%s): %s" % (pwd_file, p.returncode, to_text(stderr)))
|
602
705
|
secret = stdout
|
603
706
|
|
604
707
|
else:
|
605
708
|
try:
|
606
|
-
|
607
|
-
|
608
|
-
f.close()
|
709
|
+
with open(b_pwd_file, "rb") as password_file:
|
710
|
+
secret = password_file.read().strip()
|
609
711
|
except (OSError, IOError) as e:
|
610
712
|
raise AnsibleError("Could not read password file %s: %s" % (pwd_file, e))
|
611
713
|
|
@@ -614,7 +716,7 @@ class CLI(ABC):
|
|
614
716
|
if not secret:
|
615
717
|
raise AnsibleError('Empty password was provided from file (%s)' % pwd_file)
|
616
718
|
|
617
|
-
return
|
719
|
+
return to_text(secret)
|
618
720
|
|
619
721
|
@classmethod
|
620
722
|
def cli_executor(cls, args=None):
|
@@ -635,54 +737,22 @@ class CLI(ABC):
|
|
635
737
|
else:
|
636
738
|
display.debug("Created the '%s' directory" % ansible_dir)
|
637
739
|
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
exit_code = 6
|
644
|
-
else:
|
645
|
-
cli = cls(args)
|
646
|
-
exit_code = cli.run()
|
647
|
-
|
648
|
-
except AnsibleOptionsError as e:
|
649
|
-
cli.parser.print_help()
|
650
|
-
display.error(to_text(e), wrap_text=False)
|
651
|
-
exit_code = 5
|
652
|
-
except AnsibleParserError as e:
|
653
|
-
display.error(to_text(e), wrap_text=False)
|
654
|
-
exit_code = 4
|
655
|
-
# TQM takes care of these, but leaving comment to reserve the exit codes
|
656
|
-
# except AnsibleHostUnreachable as e:
|
657
|
-
# display.error(str(e))
|
658
|
-
# exit_code = 3
|
659
|
-
# except AnsibleHostFailed as e:
|
660
|
-
# display.error(str(e))
|
661
|
-
# exit_code = 2
|
662
|
-
except AnsibleError as e:
|
663
|
-
display.error(to_text(e), wrap_text=False)
|
664
|
-
exit_code = 1
|
740
|
+
cli = cls(args)
|
741
|
+
exit_code = cli.run()
|
742
|
+
except AnsibleError as ex:
|
743
|
+
display.error(ex)
|
744
|
+
exit_code = ex._exit_code
|
665
745
|
except KeyboardInterrupt:
|
666
746
|
display.error("User interrupted execution")
|
667
|
-
exit_code =
|
668
|
-
except Exception as
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
if hasattr(e, 'orig_exc'):
|
678
|
-
display.vvv('\nexception type: %s' % to_text(type(e.orig_exc)))
|
679
|
-
why = to_text(e.orig_exc)
|
680
|
-
if to_text(e) != why:
|
681
|
-
display.vvv('\noriginal msg: %s' % why)
|
682
|
-
else:
|
683
|
-
display.display("to see the full traceback, use -vvv")
|
684
|
-
log_only = True
|
685
|
-
display.display(u"the full traceback was:\n\n%s" % to_text(traceback.format_exc()), log_only=log_only)
|
686
|
-
exit_code = 250
|
747
|
+
exit_code = ExitCode.KEYBOARD_INTERRUPT
|
748
|
+
except Exception as ex:
|
749
|
+
try:
|
750
|
+
raise AnsibleError("Unexpected Exception, this is probably a bug.") from ex
|
751
|
+
except AnsibleError as ex2:
|
752
|
+
# DTFIX-RELEASE: clean this up so we're not hacking the internals- re-wrap in an AnsibleCLIUnhandledError that always shows TB, or?
|
753
|
+
from ansible.module_utils._internal import _traceback
|
754
|
+
_traceback._is_traceback_enabled = lambda *_args, **_kwargs: True
|
755
|
+
display.error(ex2)
|
756
|
+
exit_code = ExitCode.UNKNOWN_ERROR
|
687
757
|
|
688
758
|
sys.exit(exit_code)
|