ansible-core 2.18.7__py3-none-any.whl → 2.19.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ansible-core might be problematic. Click here for more details.
- ansible/_internal/__init__.py +53 -0
- ansible/_internal/_ansiballz/__init__.py +0 -0
- ansible/_internal/_ansiballz/_builder.py +101 -0
- ansible/_internal/_ansiballz/_wrapper.py +262 -0
- ansible/_internal/_collection_proxy.py +47 -0
- ansible/_internal/_datatag/__init__.py +0 -0
- ansible/_internal/_datatag/_tags.py +130 -0
- ansible/_internal/_datatag/_utils.py +19 -0
- ansible/_internal/_datatag/_wrappers.py +33 -0
- ansible/_internal/_errors/__init__.py +0 -0
- ansible/_internal/_errors/_alarm_timeout.py +66 -0
- ansible/_internal/_errors/_captured.py +123 -0
- ansible/_internal/_errors/_error_factory.py +89 -0
- ansible/_internal/_errors/_error_utils.py +240 -0
- ansible/_internal/_errors/_handler.py +91 -0
- ansible/_internal/_errors/_task_timeout.py +28 -0
- ansible/_internal/_event_formatting.py +127 -0
- ansible/_internal/_json/__init__.py +214 -0
- ansible/_internal/_json/_legacy_encoder.py +34 -0
- ansible/_internal/_json/_profiles/__init__.py +0 -0
- ansible/_internal/_json/_profiles/_cache_persistence.py +57 -0
- ansible/_internal/_json/_profiles/_inventory_legacy.py +40 -0
- ansible/_internal/_json/_profiles/_legacy.py +189 -0
- ansible/_internal/_locking.py +21 -0
- ansible/_internal/_plugins/__init__.py +0 -0
- ansible/_internal/_plugins/_cache.py +57 -0
- ansible/_internal/_ssh/__init__.py +0 -0
- ansible/_internal/_ssh/_agent_launch.py +91 -0
- ansible/_internal/_ssh/_ssh_agent.py +619 -0
- ansible/_internal/_task.py +78 -0
- ansible/_internal/_templating/__init__.py +12 -0
- ansible/_internal/_templating/_access.py +86 -0
- ansible/_internal/_templating/_chain_templar.py +63 -0
- ansible/_internal/_templating/_datatag.py +95 -0
- ansible/_internal/_templating/_engine.py +592 -0
- ansible/_internal/_templating/_errors.py +28 -0
- ansible/_internal/_templating/_jinja_bits.py +1106 -0
- ansible/_internal/_templating/_jinja_common.py +323 -0
- ansible/_internal/_templating/_jinja_patches.py +44 -0
- ansible/_internal/_templating/_jinja_plugins.py +375 -0
- ansible/_internal/_templating/_lazy_containers.py +633 -0
- ansible/_internal/_templating/_marker_behaviors.py +103 -0
- ansible/_internal/_templating/_template_vars.py +72 -0
- ansible/_internal/_templating/_transform.py +70 -0
- ansible/_internal/_templating/_utils.py +108 -0
- ansible/_internal/_testing.py +26 -0
- ansible/_internal/_wrapt.py +1052 -0
- ansible/_internal/_yaml/__init__.py +0 -0
- ansible/_internal/_yaml/_constructor.py +240 -0
- ansible/_internal/_yaml/_dumper.py +70 -0
- ansible/_internal/_yaml/_errors.py +166 -0
- ansible/_internal/_yaml/_loader.py +66 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/README.md +11 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/action/debug.py +36 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/apply_trust.py +19 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/dump_object.py +27 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/finalize.py +16 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/origin.py +18 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/python_literal_eval.py +24 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/python_literal_eval.yml +33 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/tag_names.py +16 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/true_type.py +17 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/unmask.py +49 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/lookup/config.py +21 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/lookup/config.yml +2 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged.py +15 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged.yml +19 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged_with.py +18 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged_with.yml +19 -0
- ansible/cli/__init__.py +93 -104
- ansible/cli/_ssh_askpass.py +54 -0
- ansible/cli/adhoc.py +20 -10
- ansible/cli/arguments/option_helpers.py +163 -10
- ansible/cli/config.py +43 -68
- ansible/cli/console.py +13 -11
- ansible/cli/doc.py +134 -77
- ansible/cli/galaxy.py +27 -20
- ansible/cli/inventory.py +28 -28
- ansible/cli/playbook.py +4 -12
- ansible/cli/pull.py +6 -3
- ansible/cli/scripts/ansible_connection_cli_stub.py +7 -7
- ansible/cli/vault.py +12 -11
- ansible/compat/__init__.py +2 -2
- ansible/compat/importlib_resources.py +9 -12
- ansible/config/base.yml +218 -133
- ansible/config/manager.py +220 -159
- ansible/constants.py +2 -65
- ansible/errors/__init__.py +350 -256
- ansible/executor/interpreter_discovery.py +28 -149
- ansible/executor/module_common.py +480 -514
- ansible/executor/play_iterator.py +22 -27
- ansible/executor/playbook_executor.py +11 -11
- ansible/executor/powershell/async_watchdog.ps1 +97 -102
- ansible/executor/powershell/async_wrapper.ps1 +204 -153
- ansible/executor/powershell/become_wrapper.ps1 +107 -144
- ansible/executor/powershell/bootstrap_wrapper.ps1 +46 -9
- ansible/executor/powershell/coverage_wrapper.ps1 +91 -135
- ansible/executor/powershell/exec_wrapper.ps1 +675 -196
- ansible/executor/powershell/module_manifest.py +469 -265
- ansible/executor/powershell/module_wrapper.ps1 +195 -186
- ansible/executor/powershell/powershell_expand_user.ps1 +20 -0
- ansible/executor/powershell/powershell_mkdtemp.ps1 +17 -0
- ansible/executor/powershell/psrp_fetch_file.ps1 +41 -0
- ansible/executor/powershell/psrp_put_file.ps1 +122 -0
- ansible/executor/powershell/winrm_fetch_file.ps1 +46 -0
- ansible/executor/powershell/winrm_put_file.ps1 +36 -0
- ansible/executor/process/worker.py +139 -149
- ansible/executor/stats.py +5 -5
- ansible/executor/task_executor.py +270 -297
- ansible/executor/task_queue_manager.py +135 -137
- ansible/executor/task_result.py +182 -79
- ansible/galaxy/__init__.py +2 -2
- ansible/galaxy/api.py +26 -25
- ansible/galaxy/collection/__init__.py +6 -14
- ansible/galaxy/collection/concrete_artifact_manager.py +12 -21
- ansible/galaxy/dependency_resolution/dataclasses.py +14 -4
- ansible/galaxy/dependency_resolution/providers.py +4 -4
- ansible/galaxy/dependency_resolution/reporters.py +81 -0
- ansible/galaxy/role.py +6 -10
- ansible/galaxy/token.py +28 -21
- ansible/inventory/data.py +47 -57
- ansible/inventory/group.py +50 -73
- ansible/inventory/helpers.py +9 -0
- ansible/inventory/host.py +37 -54
- ansible/inventory/manager.py +79 -34
- ansible/keyword_desc.yml +1 -1
- ansible/module_utils/_internal/__init__.py +55 -0
- ansible/module_utils/_internal/_ambient_context.py +58 -0
- ansible/module_utils/_internal/_ansiballz/__init__.py +0 -0
- ansible/module_utils/_internal/_ansiballz/_extensions/__init__.py +0 -0
- ansible/module_utils/_internal/_ansiballz/_extensions/_coverage.py +45 -0
- ansible/module_utils/_internal/_ansiballz/_extensions/_pydevd.py +62 -0
- ansible/module_utils/_internal/_ansiballz/_loader.py +81 -0
- ansible/module_utils/_internal/_ansiballz/_respawn.py +32 -0
- ansible/module_utils/_internal/_ansiballz/_respawn_wrapper.py +23 -0
- ansible/module_utils/_internal/_concurrent/_daemon_threading.py +1 -0
- ansible/module_utils/_internal/_dataclass_validation.py +217 -0
- ansible/module_utils/_internal/_datatag/__init__.py +961 -0
- ansible/module_utils/_internal/_datatag/_tags.py +16 -0
- ansible/module_utils/_internal/_debugging.py +31 -0
- ansible/module_utils/_internal/_deprecator.py +157 -0
- ansible/module_utils/_internal/_errors.py +101 -0
- ansible/module_utils/_internal/_event_utils.py +61 -0
- ansible/module_utils/_internal/_json/__init__.py +63 -0
- ansible/module_utils/_internal/_json/_legacy_encoder.py +26 -0
- ansible/module_utils/_internal/_json/_profiles/__init__.py +428 -0
- ansible/module_utils/_internal/_json/_profiles/_fallback_to_str.py +73 -0
- ansible/module_utils/_internal/_json/_profiles/_module_legacy_c2m.py +33 -0
- ansible/module_utils/_internal/_json/_profiles/_module_legacy_m2c.py +37 -0
- ansible/module_utils/_internal/_json/_profiles/_module_modern_c2m.py +35 -0
- ansible/module_utils/_internal/_json/_profiles/_module_modern_m2c.py +33 -0
- ansible/module_utils/_internal/_json/_profiles/_tagless.py +52 -0
- ansible/module_utils/_internal/_messages.py +130 -0
- ansible/module_utils/_internal/_patches/__init__.py +66 -0
- ansible/module_utils/_internal/_patches/_dataclass_annotation_patch.py +53 -0
- ansible/module_utils/_internal/_patches/_socket_patch.py +34 -0
- ansible/module_utils/_internal/_patches/_sys_intern_patch.py +34 -0
- ansible/module_utils/_internal/_plugin_info.py +38 -0
- ansible/module_utils/_internal/_stack.py +22 -0
- ansible/module_utils/_internal/_testing.py +0 -0
- ansible/module_utils/_internal/_text_utils.py +6 -0
- ansible/module_utils/_internal/_traceback.py +92 -0
- ansible/module_utils/_internal/_validation.py +14 -0
- ansible/module_utils/ansible_release.py +2 -2
- ansible/module_utils/api.py +1 -2
- ansible/module_utils/basic.py +303 -202
- ansible/module_utils/common/_utils.py +24 -28
- ansible/module_utils/common/arg_spec.py +8 -3
- ansible/module_utils/common/collections.py +7 -2
- ansible/module_utils/common/dict_transformations.py +2 -2
- ansible/module_utils/common/file.py +2 -2
- ansible/module_utils/common/json.py +90 -84
- ansible/module_utils/common/locale.py +2 -2
- ansible/module_utils/common/parameters.py +27 -24
- ansible/module_utils/common/process.py +2 -3
- ansible/module_utils/common/respawn.py +11 -33
- ansible/module_utils/common/sentinel.py +66 -0
- ansible/module_utils/common/sys_info.py +8 -8
- ansible/module_utils/common/text/converters.py +16 -37
- ansible/module_utils/common/validation.py +35 -24
- ansible/module_utils/common/warnings.py +143 -25
- ansible/module_utils/common/yaml.py +29 -3
- ansible/module_utils/compat/datetime.py +33 -21
- ansible/module_utils/compat/paramiko.py +21 -10
- ansible/module_utils/compat/typing.py +6 -5
- ansible/module_utils/connection.py +10 -13
- ansible/module_utils/csharp/Ansible.Basic.cs +15 -12
- ansible/module_utils/csharp/Ansible.Become.cs +1 -0
- ansible/module_utils/csharp/Ansible.Privilege.cs +2 -2
- ansible/module_utils/csharp/Ansible._Async.cs +517 -0
- ansible/module_utils/datatag.py +49 -0
- ansible/module_utils/distro/__init__.py +2 -2
- ansible/module_utils/facts/ansible_collector.py +4 -5
- ansible/module_utils/facts/collector.py +13 -14
- ansible/module_utils/facts/compat.py +4 -4
- ansible/module_utils/facts/default_collectors.py +1 -1
- ansible/module_utils/facts/hardware/aix.py +34 -0
- ansible/module_utils/facts/hardware/base.py +2 -2
- ansible/module_utils/facts/hardware/darwin.py +1 -3
- ansible/module_utils/facts/hardware/freebsd.py +2 -2
- ansible/module_utils/facts/hardware/linux.py +5 -5
- ansible/module_utils/facts/namespace.py +1 -1
- ansible/module_utils/facts/network/base.py +1 -1
- ansible/module_utils/facts/network/fc_wwn.py +1 -2
- ansible/module_utils/facts/network/iscsi.py +1 -2
- ansible/module_utils/facts/network/nvme.py +1 -2
- ansible/module_utils/facts/other/facter.py +2 -3
- ansible/module_utils/facts/other/ohai.py +2 -3
- ansible/module_utils/facts/sysctl.py +4 -6
- ansible/module_utils/facts/system/apparmor.py +1 -2
- ansible/module_utils/facts/system/caps.py +3 -3
- ansible/module_utils/facts/system/chroot.py +1 -2
- ansible/module_utils/facts/system/cmdline.py +1 -2
- ansible/module_utils/facts/system/date_time.py +5 -3
- ansible/module_utils/facts/system/distribution.py +27 -13
- ansible/module_utils/facts/system/dns.py +1 -1
- ansible/module_utils/facts/system/env.py +1 -2
- ansible/module_utils/facts/system/fips.py +7 -20
- ansible/module_utils/facts/system/loadavg.py +1 -2
- ansible/module_utils/facts/system/local.py +2 -3
- ansible/module_utils/facts/system/lsb.py +1 -2
- ansible/module_utils/facts/system/pkg_mgr.py +1 -2
- ansible/module_utils/facts/system/platform.py +1 -2
- ansible/module_utils/facts/system/python.py +1 -2
- ansible/module_utils/facts/system/selinux.py +1 -1
- ansible/module_utils/facts/system/service_mgr.py +1 -2
- ansible/module_utils/facts/system/ssh_pub_keys.py +1 -1
- ansible/module_utils/facts/system/systemd.py +1 -1
- ansible/module_utils/facts/system/user.py +1 -2
- ansible/module_utils/facts/utils.py +3 -3
- ansible/module_utils/facts/virtual/base.py +1 -1
- ansible/module_utils/facts/virtual/linux.py +3 -3
- ansible/module_utils/facts/virtual/sunos.py +3 -15
- ansible/module_utils/facts/virtual/sysctl.py +3 -16
- ansible/module_utils/json_utils.py +2 -2
- ansible/module_utils/parsing/convert_bool.py +7 -1
- ansible/module_utils/powershell/Ansible.ModuleUtils.AddType.psm1 +1 -1
- ansible/module_utils/powershell/Ansible.ModuleUtils.CamelConversion.psm1 +1 -1
- ansible/module_utils/powershell/Ansible.ModuleUtils.CommandUtil.psm1 +1 -1
- ansible/module_utils/powershell/Ansible.ModuleUtils.WebRequest.psm1 +1 -1
- ansible/module_utils/service.py +21 -31
- ansible/module_utils/splitter.py +7 -7
- ansible/module_utils/testing.py +31 -0
- ansible/module_utils/urls.py +64 -35
- ansible/modules/add_host.py +4 -4
- ansible/modules/apt.py +69 -49
- ansible/modules/apt_key.py +19 -12
- ansible/modules/apt_repository.py +32 -51
- ansible/modules/assemble.py +16 -14
- ansible/modules/assert.py +4 -4
- ansible/modules/async_status.py +24 -24
- ansible/modules/async_wrapper.py +20 -25
- ansible/modules/blockinfile.py +6 -7
- ansible/modules/command.py +13 -20
- ansible/modules/copy.py +60 -147
- ansible/modules/cron.py +24 -21
- ansible/modules/deb822_repository.py +8 -9
- ansible/modules/debconf.py +5 -5
- ansible/modules/debug.py +4 -4
- ansible/modules/dnf.py +8 -8
- ansible/modules/dnf5.py +39 -13
- ansible/modules/dpkg_selections.py +4 -4
- ansible/modules/expect.py +13 -15
- ansible/modules/fail.py +4 -4
- ansible/modules/fetch.py +4 -4
- ansible/modules/file.py +184 -144
- ansible/modules/find.py +22 -20
- ansible/modules/gather_facts.py +3 -3
- ansible/modules/get_url.py +77 -54
- ansible/modules/getent.py +7 -9
- ansible/modules/git.py +38 -38
- ansible/modules/group.py +6 -6
- ansible/modules/group_by.py +4 -4
- ansible/modules/hostname.py +15 -32
- ansible/modules/import_playbook.py +6 -6
- ansible/modules/import_role.py +6 -6
- ansible/modules/import_tasks.py +6 -6
- ansible/modules/include_role.py +6 -6
- ansible/modules/include_tasks.py +6 -6
- ansible/modules/include_vars.py +6 -6
- ansible/modules/iptables.py +86 -73
- ansible/modules/known_hosts.py +22 -24
- ansible/modules/lineinfile.py +5 -5
- ansible/modules/meta.py +4 -4
- ansible/modules/mount_facts.py +2 -2
- ansible/modules/package.py +10 -4
- ansible/modules/package_facts.py +22 -10
- ansible/modules/pause.py +6 -6
- ansible/modules/ping.py +6 -6
- ansible/modules/pip.py +21 -26
- ansible/modules/raw.py +6 -6
- ansible/modules/reboot.py +6 -6
- ansible/modules/replace.py +10 -14
- ansible/modules/rpm_key.py +7 -8
- ansible/modules/script.py +4 -4
- ansible/modules/service.py +10 -17
- ansible/modules/service_facts.py +87 -10
- ansible/modules/set_fact.py +5 -5
- ansible/modules/set_stats.py +4 -4
- ansible/modules/setup.py +2 -2
- ansible/modules/shell.py +6 -6
- ansible/modules/slurp.py +16 -19
- ansible/modules/stat.py +15 -31
- ansible/modules/subversion.py +15 -15
- ansible/modules/systemd.py +7 -7
- ansible/modules/systemd_service.py +7 -7
- ansible/modules/sysvinit.py +9 -9
- ansible/modules/tempfile.py +5 -6
- ansible/modules/template.py +6 -6
- ansible/modules/unarchive.py +38 -17
- ansible/modules/uri.py +33 -26
- ansible/modules/user.py +45 -32
- ansible/modules/validate_argument_spec.py +10 -7
- ansible/modules/wait_for.py +70 -60
- ansible/modules/wait_for_connection.py +6 -6
- ansible/modules/yum_repository.py +10 -9
- ansible/parsing/ajson.py +17 -37
- ansible/parsing/dataloader.py +99 -54
- ansible/parsing/mod_args.py +62 -60
- ansible/parsing/plugin_docs.py +21 -86
- ansible/parsing/quoting.py +1 -1
- ansible/parsing/splitter.py +27 -12
- ansible/parsing/utils/addresses.py +24 -24
- ansible/parsing/utils/jsonify.py +5 -1
- ansible/parsing/utils/yaml.py +32 -61
- ansible/parsing/vault/__init__.py +327 -99
- ansible/parsing/yaml/__init__.py +0 -18
- ansible/parsing/yaml/dumper.py +6 -120
- ansible/parsing/yaml/loader.py +6 -39
- ansible/parsing/yaml/objects.py +43 -335
- ansible/playbook/__init__.py +1 -1
- ansible/playbook/attribute.py +8 -3
- ansible/playbook/base.py +187 -134
- ansible/playbook/block.py +26 -24
- ansible/playbook/collectionsearch.py +1 -15
- ansible/playbook/conditional.py +3 -77
- ansible/playbook/handler.py +8 -2
- ansible/playbook/helpers.py +41 -53
- ansible/playbook/included_file.py +32 -26
- ansible/playbook/loop_control.py +2 -2
- ansible/playbook/play.py +85 -44
- ansible/playbook/play_context.py +14 -17
- ansible/playbook/playbook_include.py +27 -62
- ansible/playbook/role/__init__.py +64 -49
- ansible/playbook/role/definition.py +15 -17
- ansible/playbook/role/include.py +2 -4
- ansible/playbook/role/metadata.py +10 -11
- ansible/playbook/role_include.py +3 -3
- ansible/playbook/taggable.py +28 -12
- ansible/playbook/task.py +192 -121
- ansible/playbook/task_include.py +5 -5
- ansible/plugins/__init__.py +58 -26
- ansible/plugins/action/__init__.py +188 -186
- ansible/plugins/action/add_host.py +2 -2
- ansible/plugins/action/assemble.py +11 -18
- ansible/plugins/action/assert.py +55 -67
- ansible/plugins/action/async_status.py +7 -2
- ansible/plugins/action/copy.py +14 -17
- ansible/plugins/action/debug.py +37 -31
- ansible/plugins/action/dnf.py +3 -4
- ansible/plugins/action/fail.py +1 -1
- ansible/plugins/action/fetch.py +7 -8
- ansible/plugins/action/gather_facts.py +13 -14
- ansible/plugins/action/group_by.py +1 -1
- ansible/plugins/action/include_vars.py +10 -11
- ansible/plugins/action/package.py +8 -14
- ansible/plugins/action/pause.py +2 -2
- ansible/plugins/action/script.py +27 -38
- ansible/plugins/action/service.py +9 -18
- ansible/plugins/action/set_fact.py +3 -12
- ansible/plugins/action/set_stats.py +3 -8
- ansible/plugins/action/template.py +47 -67
- ansible/plugins/action/unarchive.py +6 -16
- ansible/plugins/action/uri.py +9 -20
- ansible/plugins/action/validate_argument_spec.py +5 -5
- ansible/plugins/action/wait_for_connection.py +1 -1
- ansible/plugins/become/__init__.py +31 -8
- ansible/plugins/become/runas.py +71 -0
- ansible/plugins/become/su.py +13 -8
- ansible/plugins/become/sudo.py +19 -0
- ansible/plugins/cache/__init__.py +52 -63
- ansible/plugins/cache/base.py +8 -0
- ansible/plugins/cache/jsonfile.py +10 -16
- ansible/plugins/cache/memory.py +6 -12
- ansible/plugins/callback/__init__.py +294 -201
- ansible/plugins/callback/default.py +99 -95
- ansible/plugins/callback/junit.py +44 -43
- ansible/plugins/callback/minimal.py +28 -25
- ansible/plugins/callback/oneline.py +34 -21
- ansible/plugins/callback/tree.py +27 -16
- ansible/plugins/connection/__init__.py +47 -34
- ansible/plugins/connection/local.py +156 -60
- ansible/plugins/connection/paramiko_ssh.py +34 -24
- ansible/plugins/connection/psrp.py +76 -165
- ansible/plugins/connection/ssh.py +326 -86
- ansible/plugins/connection/winrm.py +62 -141
- ansible/plugins/doc_fragments/action_common_attributes.py +14 -14
- ansible/plugins/doc_fragments/action_core.py +6 -6
- ansible/plugins/doc_fragments/backup.py +2 -2
- ansible/plugins/doc_fragments/checksum_common.py +27 -0
- ansible/plugins/doc_fragments/constructed.py +8 -4
- ansible/plugins/doc_fragments/decrypt.py +2 -2
- ansible/plugins/doc_fragments/default_callback.py +2 -2
- ansible/plugins/doc_fragments/files.py +2 -2
- ansible/plugins/doc_fragments/inventory_cache.py +2 -2
- ansible/plugins/doc_fragments/result_format_callback.py +2 -2
- ansible/plugins/doc_fragments/return_common.py +2 -2
- ansible/plugins/doc_fragments/template_common.py +4 -4
- ansible/plugins/doc_fragments/url.py +17 -1
- ansible/plugins/doc_fragments/url_windows.py +2 -2
- ansible/plugins/doc_fragments/validate.py +2 -2
- ansible/plugins/doc_fragments/vars_plugin_staging.py +2 -2
- ansible/plugins/filter/__init__.py +6 -2
- ansible/plugins/filter/b64decode.yml +22 -0
- ansible/plugins/filter/b64encode.yml +22 -0
- ansible/plugins/filter/bool.yml +11 -4
- ansible/plugins/filter/core.py +245 -120
- ansible/plugins/filter/encryption.py +42 -34
- ansible/plugins/filter/flatten.yml +3 -2
- ansible/plugins/filter/human_to_bytes.yml +1 -1
- ansible/plugins/filter/mathstuff.py +30 -37
- ansible/plugins/filter/password_hash.yml +8 -0
- ansible/plugins/filter/pow.yml +1 -1
- ansible/plugins/filter/regex_search.yml +1 -4
- ansible/plugins/filter/root.yml +1 -1
- ansible/plugins/filter/split.yml +1 -1
- ansible/plugins/filter/strftime.yml +3 -3
- ansible/plugins/filter/to_nice_yaml.yml +0 -4
- ansible/plugins/filter/to_uuid.yml +1 -1
- ansible/plugins/filter/to_yaml.yml +0 -4
- ansible/plugins/filter/unvault.yml +1 -1
- ansible/plugins/filter/urls.py +1 -1
- ansible/plugins/filter/urlsplit.py +8 -9
- ansible/plugins/filter/vault.yml +14 -9
- ansible/plugins/filter/win_basename.yml +6 -1
- ansible/plugins/filter/win_dirname.yml +5 -0
- ansible/plugins/inventory/__init__.py +107 -86
- ansible/plugins/inventory/advanced_host_list.py +7 -5
- ansible/plugins/inventory/auto.py +11 -4
- ansible/plugins/inventory/constructed.py +21 -24
- ansible/plugins/inventory/generator.py +16 -11
- ansible/plugins/inventory/host_list.py +7 -5
- ansible/plugins/inventory/ini.py +78 -44
- ansible/plugins/inventory/script.py +190 -120
- ansible/plugins/inventory/toml.py +16 -126
- ansible/plugins/inventory/yaml.py +10 -8
- ansible/plugins/list.py +72 -19
- ansible/plugins/loader.py +383 -198
- ansible/plugins/lookup/__init__.py +21 -4
- ansible/plugins/lookup/config.py +21 -35
- ansible/plugins/lookup/csvfile.py +19 -73
- ansible/plugins/lookup/dict.py +1 -6
- ansible/plugins/lookup/env.py +12 -9
- ansible/plugins/lookup/file.py +5 -8
- ansible/plugins/lookup/first_found.py +87 -55
- ansible/plugins/lookup/indexed_items.py +1 -10
- ansible/plugins/lookup/ini.py +14 -13
- ansible/plugins/lookup/items.py +1 -1
- ansible/plugins/lookup/lines.py +8 -1
- ansible/plugins/lookup/list.py +1 -1
- ansible/plugins/lookup/nested.py +2 -18
- ansible/plugins/lookup/password.py +5 -5
- ansible/plugins/lookup/pipe.py +5 -7
- ansible/plugins/lookup/sequence.py +18 -8
- ansible/plugins/lookup/subelements.py +1 -4
- ansible/plugins/lookup/template.py +47 -36
- ansible/plugins/lookup/together.py +0 -12
- ansible/plugins/lookup/unvault.py +1 -5
- ansible/plugins/lookup/url.py +4 -10
- ansible/plugins/lookup/vars.py +16 -24
- ansible/plugins/shell/__init__.py +58 -4
- ansible/plugins/shell/cmd.py +2 -2
- ansible/plugins/shell/powershell.py +106 -31
- ansible/plugins/shell/sh.py +13 -7
- ansible/plugins/strategy/__init__.py +168 -193
- ansible/plugins/strategy/debug.py +2 -2
- ansible/plugins/strategy/free.py +16 -31
- ansible/plugins/strategy/host_pinned.py +2 -2
- ansible/plugins/strategy/linear.py +41 -41
- ansible/plugins/terminal/__init__.py +4 -4
- ansible/plugins/test/__init__.py +7 -2
- ansible/plugins/test/core.py +75 -35
- ansible/plugins/test/files.py +1 -1
- ansible/plugins/test/finished.yml +1 -1
- ansible/plugins/test/mathstuff.py +3 -3
- ansible/plugins/test/uri.py +5 -8
- ansible/plugins/vars/host_group_vars.py +7 -14
- ansible/release.py +2 -2
- ansible/template/__init__.py +353 -943
- ansible/utils/__init__.py +0 -18
- ansible/utils/collection_loader/__init__.py +54 -5
- ansible/utils/collection_loader/_collection_config.py +5 -6
- ansible/utils/collection_loader/_collection_finder.py +82 -96
- ansible/utils/collection_loader/_collection_meta.py +15 -8
- ansible/utils/display.py +485 -73
- ansible/utils/encrypt.py +27 -19
- ansible/utils/fqcn.py +2 -2
- ansible/utils/galaxy.py +2 -2
- ansible/utils/hashing.py +8 -10
- ansible/utils/helpers.py +2 -2
- ansible/utils/listify.py +10 -8
- ansible/utils/lock.py +2 -2
- ansible/utils/path.py +10 -12
- ansible/utils/plugin_docs.py +16 -14
- ansible/utils/py3compat.py +2 -7
- ansible/utils/sentinel.py +4 -62
- ansible/utils/singleton.py +2 -0
- ansible/utils/ssh_functions.py +6 -2
- ansible/utils/unsafe_proxy.py +23 -332
- ansible/utils/vars.py +55 -8
- ansible/utils/version.py +2 -2
- ansible/vars/clean.py +5 -5
- ansible/vars/hostvars.py +60 -90
- ansible/vars/manager.py +220 -285
- ansible/vars/plugins.py +4 -4
- ansible/vars/reserved.py +13 -12
- {ansible_core-2.18.7.dist-info → ansible_core-2.19.0.dist-info}/METADATA +4 -3
- ansible_core-2.19.0.dist-info/RECORD +1097 -0
- ansible_core-2.19.0.dist-info/licenses/licenses/BSD-3-Clause.txt +28 -0
- ansible_test/_data/completion/docker.txt +7 -7
- ansible_test/_data/completion/remote.txt +6 -6
- ansible_test/_data/completion/windows.txt +1 -0
- ansible_test/_data/requirements/ansible.txt +2 -2
- ansible_test/_data/requirements/sanity.ansible-doc.txt +3 -3
- ansible_test/_data/requirements/sanity.changelog.txt +2 -2
- ansible_test/_data/requirements/sanity.import.plugin.txt +2 -2
- ansible_test/_data/requirements/sanity.pep8.txt +1 -1
- ansible_test/_data/requirements/sanity.pylint.txt +5 -5
- ansible_test/_data/requirements/sanity.validate-modules.txt +2 -2
- ansible_test/_data/requirements/sanity.yamllint.txt +1 -1
- ansible_test/_data/requirements/units.txt +1 -0
- ansible_test/_internal/__init__.py +6 -0
- ansible_test/_internal/ansible_util.py +3 -1
- ansible_test/_internal/become.py +1 -0
- ansible_test/_internal/bootstrap.py +1 -0
- ansible_test/_internal/cache.py +1 -0
- ansible_test/_internal/cgroup.py +1 -0
- ansible_test/_internal/ci/__init__.py +1 -0
- ansible_test/_internal/ci/azp.py +1 -0
- ansible_test/_internal/ci/local.py +1 -0
- ansible_test/_internal/classification/__init__.py +1 -0
- ansible_test/_internal/classification/common.py +1 -0
- ansible_test/_internal/classification/csharp.py +1 -0
- ansible_test/_internal/classification/powershell.py +1 -0
- ansible_test/_internal/classification/python.py +1 -0
- ansible_test/_internal/cli/__init__.py +1 -0
- ansible_test/_internal/cli/actions.py +1 -0
- ansible_test/_internal/cli/argparsing/__init__.py +1 -0
- ansible_test/_internal/cli/argparsing/actions.py +1 -0
- ansible_test/_internal/cli/argparsing/argcompletion.py +1 -0
- ansible_test/_internal/cli/argparsing/parsers.py +1 -0
- ansible_test/_internal/cli/commands/__init__.py +11 -5
- ansible_test/_internal/cli/commands/coverage/__init__.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/__init__.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/__init__.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/combine.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/expand.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/filter.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/generate.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/missing.py +1 -0
- ansible_test/_internal/cli/commands/coverage/combine.py +1 -0
- ansible_test/_internal/cli/commands/coverage/erase.py +1 -0
- ansible_test/_internal/cli/commands/coverage/html.py +1 -0
- ansible_test/_internal/cli/commands/coverage/report.py +1 -0
- ansible_test/_internal/cli/commands/coverage/xml.py +1 -0
- ansible_test/_internal/cli/commands/env.py +1 -0
- ansible_test/_internal/cli/commands/integration/__init__.py +1 -0
- ansible_test/_internal/cli/commands/integration/network.py +1 -0
- ansible_test/_internal/cli/commands/integration/posix.py +1 -0
- ansible_test/_internal/cli/commands/integration/windows.py +1 -0
- ansible_test/_internal/cli/commands/sanity.py +9 -0
- ansible_test/_internal/cli/commands/shell.py +1 -0
- ansible_test/_internal/cli/commands/units.py +1 -0
- ansible_test/_internal/cli/compat.py +1 -0
- ansible_test/_internal/cli/completers.py +1 -0
- ansible_test/_internal/cli/converters.py +1 -0
- ansible_test/_internal/cli/environments.py +52 -5
- ansible_test/_internal/cli/epilog.py +1 -0
- ansible_test/_internal/cli/parsers/__init__.py +1 -0
- ansible_test/_internal/cli/parsers/base_argument_parsers.py +1 -0
- ansible_test/_internal/cli/parsers/helpers.py +1 -0
- ansible_test/_internal/cli/parsers/host_config_parsers.py +1 -0
- ansible_test/_internal/cli/parsers/key_value_parsers.py +1 -0
- ansible_test/_internal/cli/parsers/value_parsers.py +1 -0
- ansible_test/_internal/commands/__init__.py +1 -0
- ansible_test/_internal/commands/coverage/__init__.py +3 -2
- ansible_test/_internal/commands/coverage/analyze/__init__.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/__init__.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/combine.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/expand.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/filter.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/generate.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/missing.py +1 -0
- ansible_test/_internal/commands/coverage/combine.py +2 -1
- ansible_test/_internal/commands/coverage/erase.py +1 -0
- ansible_test/_internal/commands/coverage/html.py +1 -0
- ansible_test/_internal/commands/coverage/report.py +1 -0
- ansible_test/_internal/commands/coverage/xml.py +1 -0
- ansible_test/_internal/commands/env/__init__.py +2 -0
- ansible_test/_internal/commands/integration/__init__.py +22 -5
- ansible_test/_internal/commands/integration/cloud/__init__.py +1 -0
- ansible_test/_internal/commands/integration/cloud/acme.py +2 -1
- ansible_test/_internal/commands/integration/cloud/aws.py +1 -0
- ansible_test/_internal/commands/integration/cloud/azure.py +1 -0
- ansible_test/_internal/commands/integration/cloud/cs.py +1 -0
- ansible_test/_internal/commands/integration/cloud/digitalocean.py +1 -0
- ansible_test/_internal/commands/integration/cloud/galaxy.py +3 -2
- ansible_test/_internal/commands/integration/cloud/hcloud.py +1 -0
- ansible_test/_internal/commands/integration/cloud/httptester.py +3 -2
- ansible_test/_internal/commands/integration/cloud/nios.py +2 -1
- ansible_test/_internal/commands/integration/cloud/opennebula.py +1 -0
- ansible_test/_internal/commands/integration/cloud/openshift.py +1 -0
- ansible_test/_internal/commands/integration/cloud/scaleway.py +1 -0
- ansible_test/_internal/commands/integration/cloud/vcenter.py +1 -0
- ansible_test/_internal/commands/integration/cloud/vultr.py +1 -0
- ansible_test/_internal/commands/integration/coverage.py +8 -2
- ansible_test/_internal/commands/integration/filters.py +1 -0
- ansible_test/_internal/commands/integration/network.py +1 -0
- ansible_test/_internal/commands/integration/posix.py +1 -0
- ansible_test/_internal/commands/integration/windows.py +1 -0
- ansible_test/_internal/commands/sanity/__init__.py +19 -2
- ansible_test/_internal/commands/sanity/ansible_doc.py +1 -0
- ansible_test/_internal/commands/sanity/bin_symlinks.py +1 -0
- ansible_test/_internal/commands/sanity/compile.py +1 -0
- ansible_test/_internal/commands/sanity/ignores.py +1 -0
- ansible_test/_internal/commands/sanity/import.py +1 -0
- ansible_test/_internal/commands/sanity/integration_aliases.py +12 -0
- ansible_test/_internal/commands/sanity/pep8.py +1 -0
- ansible_test/_internal/commands/sanity/pslint.py +1 -0
- ansible_test/_internal/commands/sanity/pylint.py +25 -26
- ansible_test/_internal/commands/sanity/shellcheck.py +1 -0
- ansible_test/_internal/commands/sanity/validate_modules.py +1 -0
- ansible_test/_internal/commands/sanity/yamllint.py +1 -0
- ansible_test/_internal/commands/shell/__init__.py +44 -4
- ansible_test/_internal/commands/units/__init__.py +5 -1
- ansible_test/_internal/compat/__init__.py +1 -0
- ansible_test/_internal/compat/packaging.py +1 -0
- ansible_test/_internal/compat/yaml.py +1 -0
- ansible_test/_internal/completion.py +1 -0
- ansible_test/_internal/config.py +23 -13
- ansible_test/_internal/connections.py +1 -0
- ansible_test/_internal/constants.py +1 -0
- ansible_test/_internal/containers.py +1 -0
- ansible_test/_internal/content_config.py +1 -0
- ansible_test/_internal/core_ci.py +1 -0
- ansible_test/_internal/coverage_util.py +11 -10
- ansible_test/_internal/data.py +1 -0
- ansible_test/_internal/debugging.py +166 -0
- ansible_test/_internal/delegation.py +22 -13
- ansible_test/_internal/dev/__init__.py +1 -0
- ansible_test/_internal/dev/container_probe.py +1 -0
- ansible_test/_internal/diff.py +3 -2
- ansible_test/_internal/docker_util.py +2 -1
- ansible_test/_internal/encoding.py +1 -0
- ansible_test/_internal/executor.py +1 -0
- ansible_test/_internal/git.py +1 -0
- ansible_test/_internal/host_configs.py +1 -0
- ansible_test/_internal/host_profiles.py +260 -16
- ansible_test/_internal/http.py +1 -0
- ansible_test/_internal/init.py +1 -0
- ansible_test/_internal/inventory.py +39 -3
- ansible_test/_internal/io.py +1 -0
- ansible_test/_internal/metadata.py +95 -4
- ansible_test/_internal/payload.py +1 -0
- ansible_test/_internal/processes.py +80 -0
- ansible_test/_internal/provider/__init__.py +1 -0
- ansible_test/_internal/provider/layout/__init__.py +1 -0
- ansible_test/_internal/provider/layout/ansible.py +1 -0
- ansible_test/_internal/provider/layout/collection.py +1 -0
- ansible_test/_internal/provider/layout/unsupported.py +1 -0
- ansible_test/_internal/provider/source/__init__.py +1 -0
- ansible_test/_internal/provider/source/git.py +1 -0
- ansible_test/_internal/provider/source/installed.py +1 -0
- ansible_test/_internal/provider/source/unsupported.py +1 -0
- ansible_test/_internal/provider/source/unversioned.py +1 -0
- ansible_test/_internal/provisioning.py +11 -4
- ansible_test/_internal/pypi_proxy.py +6 -5
- ansible_test/_internal/python_requirements.py +28 -0
- ansible_test/_internal/ssh.py +2 -5
- ansible_test/_internal/target.py +9 -0
- ansible_test/_internal/test.py +3 -2
- ansible_test/_internal/thread.py +3 -1
- ansible_test/_internal/timeout.py +2 -1
- ansible_test/_internal/util.py +41 -12
- ansible_test/_internal/util_common.py +18 -5
- ansible_test/_internal/venv.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/action-plugin-docs.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/changelog/sphinx.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/changelog.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/empty-init.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/line-endings.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-assert.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-get-exception.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-illegal-filenames.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-smart-quotes.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/replace-urlopen.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/runtime-metadata.py +28 -1
- ansible_test/_util/controller/sanity/code-smell/shebang.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/symlinks.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/use-argspec-type-path.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/use-compat-six.py +1 -0
- ansible_test/_util/controller/sanity/integration-aliases/yaml_to_json.py +2 -1
- ansible_test/_util/controller/sanity/pep8/current-ignore.txt +4 -0
- ansible_test/_util/controller/sanity/pylint/config/ansible-test-target.cfg +8 -5
- ansible_test/_util/controller/sanity/pylint/config/ansible-test.cfg +8 -5
- ansible_test/_util/controller/sanity/pylint/config/code-smell.cfg +8 -5
- ansible_test/_util/controller/sanity/pylint/config/collection.cfg +4 -5
- ansible_test/_util/controller/sanity/pylint/config/default.cfg +8 -7
- ansible_test/_util/controller/sanity/pylint/plugins/deprecated_calls.py +541 -0
- ansible_test/_util/controller/sanity/pylint/plugins/deprecated_comment.py +137 -0
- ansible_test/_util/controller/sanity/pylint/plugins/hide_unraisable.py +1 -0
- ansible_test/_util/controller/sanity/pylint/plugins/string_format.py +1 -8
- ansible_test/_util/controller/sanity/pylint/plugins/unwanted.py +1 -8
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py +55 -28
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/module_args.py +12 -5
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/schema.py +13 -2
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/utils.py +1 -0
- ansible_test/_util/controller/sanity/yamllint/yamllinter.py +35 -17
- ansible_test/_util/controller/tools/collection_detail.py +1 -0
- ansible_test/_util/controller/tools/yaml_to_json.py +2 -1
- ansible_test/_util/target/injector/python.py +8 -0
- ansible_test/_util/target/pytest/plugins/ansible_forked.py +6 -1
- ansible_test/_util/target/pytest/plugins/ansible_pytest_collections.py +2 -1
- ansible_test/_util/target/pytest/plugins/ansible_pytest_coverage.py +1 -0
- ansible_test/_util/target/sanity/compile/compile.py +1 -0
- ansible_test/_util/target/sanity/import/importer.py +15 -16
- ansible_test/_util/target/setup/bootstrap.sh +9 -20
- ansible_test/_util/target/setup/probe_cgroups.py +1 -0
- ansible_test/_util/target/setup/quiet_pip.py +1 -0
- ansible_test/_util/target/setup/requirements.py +38 -36
- ansible_test/_util/target/tools/virtualenvcheck.py +2 -1
- ansible_test/_util/target/tools/yamlcheck.py +2 -1
- ansible/compat/selectors.py +0 -32
- ansible/errors/yaml_strings.py +0 -138
- ansible/executor/action_write_locks.py +0 -44
- ansible/executor/discovery/python_target.py +0 -47
- ansible/executor/powershell/module_powershell_wrapper.ps1 +0 -86
- ansible/executor/powershell/module_script_wrapper.ps1 +0 -22
- ansible/module_utils/compat/importlib.py +0 -26
- ansible/module_utils/compat/selectors.py +0 -32
- ansible/module_utils/pycompat24.py +0 -73
- ansible/parsing/yaml/constructor.py +0 -178
- ansible/template/native_helpers.py +0 -251
- ansible/template/template.py +0 -43
- ansible/template/vars.py +0 -77
- ansible/utils/native_jinja.py +0 -11
- ansible/vars/fact_cache.py +0 -71
- ansible_core-2.18.7.dist-info/RECORD +0 -992
- ansible_test/_util/controller/sanity/pylint/plugins/deprecated.py +0 -411
- {ansible_core-2.18.7.dist-info → ansible_core-2.19.0.dist-info}/WHEEL +0 -0
- {ansible_core-2.18.7.dist-info → ansible_core-2.19.0.dist-info}/entry_points.txt +0 -0
- {ansible_core-2.18.7.dist-info → ansible_core-2.19.0.dist-info}/licenses/COPYING +0 -0
- {ansible_core-2.18.7.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/Apache-License.txt +0 -0
- {ansible_core-2.18.7.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/MIT-license.txt +0 -0
- {ansible_core-2.18.7.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/PSF-license.txt +0 -0
- {ansible_core-2.18.7.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/simplified_bsd.txt +0 -0
- {ansible_core-2.18.7.dist-info → ansible_core-2.19.0.dist-info}/top_level.txt +0 -0
ansible/module_utils/basic.py
CHANGED
|
@@ -4,8 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
from __future__ import annotations
|
|
6
6
|
|
|
7
|
+
import copy
|
|
7
8
|
import json
|
|
8
9
|
import sys
|
|
10
|
+
import typing as t
|
|
9
11
|
|
|
10
12
|
# Used for determining if the system is running a new enough python version
|
|
11
13
|
# and should only restrict on our documented minimum versions
|
|
@@ -24,6 +26,7 @@ if sys.version_info < _PY_MIN:
|
|
|
24
26
|
|
|
25
27
|
import __main__
|
|
26
28
|
import atexit
|
|
29
|
+
import dataclasses as _dataclasses
|
|
27
30
|
import errno
|
|
28
31
|
import grp
|
|
29
32
|
import fcntl
|
|
@@ -50,6 +53,8 @@ try:
|
|
|
50
53
|
except ImportError:
|
|
51
54
|
HAS_SYSLOG = False
|
|
52
55
|
|
|
56
|
+
_UNSET = t.cast(t.Any, object())
|
|
57
|
+
|
|
53
58
|
try:
|
|
54
59
|
from systemd import journal, daemon as systemd_daemon
|
|
55
60
|
# Makes sure that systemd.journal has method sendv()
|
|
@@ -70,8 +75,12 @@ except ImportError:
|
|
|
70
75
|
# Python2 & 3 way to get NoneType
|
|
71
76
|
NoneType = type(None)
|
|
72
77
|
|
|
73
|
-
from .
|
|
74
|
-
|
|
78
|
+
from ._internal import _traceback, _errors, _debugging, _deprecator, _messages
|
|
79
|
+
|
|
80
|
+
from .common.text.converters import (
|
|
81
|
+
to_native,
|
|
82
|
+
to_bytes,
|
|
83
|
+
to_text,
|
|
75
84
|
jsonify,
|
|
76
85
|
container_to_bytes as json_dict_unicode_to_bytes,
|
|
77
86
|
container_to_text as json_dict_bytes_to_unicode,
|
|
@@ -86,6 +95,8 @@ from ansible.module_utils.common.text.formatters import (
|
|
|
86
95
|
SIZE_RANGES,
|
|
87
96
|
)
|
|
88
97
|
|
|
98
|
+
from ansible.module_utils.common import json as _common_json
|
|
99
|
+
|
|
89
100
|
import hashlib
|
|
90
101
|
|
|
91
102
|
|
|
@@ -110,6 +121,8 @@ def _get_available_hash_algorithms():
|
|
|
110
121
|
|
|
111
122
|
AVAILABLE_HASH_ALGORITHMS = _get_available_hash_algorithms()
|
|
112
123
|
|
|
124
|
+
from ansible.module_utils.common import json as _json
|
|
125
|
+
|
|
113
126
|
from ansible.module_utils.six.moves.collections_abc import (
|
|
114
127
|
KeysView,
|
|
115
128
|
Mapping, MutableMapping,
|
|
@@ -151,8 +164,9 @@ from ansible.module_utils.common._utils import get_all_subclasses as _get_all_su
|
|
|
151
164
|
from ansible.module_utils.parsing.convert_bool import BOOLEANS, BOOLEANS_FALSE, BOOLEANS_TRUE, boolean
|
|
152
165
|
from ansible.module_utils.common.warnings import (
|
|
153
166
|
deprecate,
|
|
154
|
-
|
|
155
|
-
|
|
167
|
+
error_as_warning,
|
|
168
|
+
get_deprecations,
|
|
169
|
+
get_warnings,
|
|
156
170
|
warn,
|
|
157
171
|
)
|
|
158
172
|
|
|
@@ -168,7 +182,9 @@ imap = map
|
|
|
168
182
|
# multiple AnsibleModules are created. Otherwise each AnsibleModule would
|
|
169
183
|
# attempt to read from stdin. Other code should not use this directly as it
|
|
170
184
|
# is an internal implementation detail
|
|
171
|
-
_ANSIBLE_ARGS = None
|
|
185
|
+
_ANSIBLE_ARGS: bytes | None = None
|
|
186
|
+
_ANSIBLE_PROFILE: str | None = None
|
|
187
|
+
_PARSED_MODULE_ARGS: dict[str, t.Any] | None = None
|
|
172
188
|
|
|
173
189
|
|
|
174
190
|
FILE_COMMON_ARGUMENTS = dict(
|
|
@@ -199,14 +215,14 @@ PERMS_RE = re.compile(r'^[rwxXstugo]*$')
|
|
|
199
215
|
#
|
|
200
216
|
|
|
201
217
|
def get_platform():
|
|
202
|
-
|
|
218
|
+
"""
|
|
203
219
|
**Deprecated** Use :py:func:`platform.system` directly.
|
|
204
220
|
|
|
205
221
|
:returns: Name of the platform the module is running on in a native string
|
|
206
222
|
|
|
207
223
|
Returns a native string that labels the platform ("Linux", "Solaris", etc). Currently, this is
|
|
208
224
|
the result of calling :py:func:`platform.system`.
|
|
209
|
-
|
|
225
|
+
"""
|
|
210
226
|
return platform.system()
|
|
211
227
|
|
|
212
228
|
# End deprecated functions
|
|
@@ -231,7 +247,7 @@ def get_all_subclasses(cls):
|
|
|
231
247
|
|
|
232
248
|
|
|
233
249
|
def heuristic_log_sanitize(data, no_log_values=None):
|
|
234
|
-
|
|
250
|
+
""" Remove strings that look like passwords from log messages """
|
|
235
251
|
# Currently filters:
|
|
236
252
|
# user:pass@foo/whatever and http://username:pass@wherever/foo
|
|
237
253
|
# This code has false positives and consumes parts of logs that are
|
|
@@ -296,7 +312,7 @@ def heuristic_log_sanitize(data, no_log_values=None):
|
|
|
296
312
|
|
|
297
313
|
|
|
298
314
|
def _load_params():
|
|
299
|
-
|
|
315
|
+
""" read the modules parameters and store them globally.
|
|
300
316
|
|
|
301
317
|
This function may be needed for certain very dynamic custom modules which
|
|
302
318
|
want to process the parameters that are being handed the module. Since
|
|
@@ -305,42 +321,32 @@ def _load_params():
|
|
|
305
321
|
will try not to break it gratuitously. It is certainly more future-proof
|
|
306
322
|
to call this function and consume its outputs than to implement the logic
|
|
307
323
|
inside it as a copy in your own code.
|
|
308
|
-
|
|
309
|
-
global _ANSIBLE_ARGS
|
|
310
|
-
if _ANSIBLE_ARGS is not None:
|
|
311
|
-
buffer = _ANSIBLE_ARGS
|
|
312
|
-
else:
|
|
313
|
-
# debug overrides to read args from file or cmdline
|
|
324
|
+
"""
|
|
325
|
+
global _ANSIBLE_ARGS, _ANSIBLE_PROFILE
|
|
314
326
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
if len(sys.argv) > 1:
|
|
318
|
-
if os.path.isfile(sys.argv[1]):
|
|
319
|
-
fd = open(sys.argv[1], 'rb')
|
|
320
|
-
buffer = fd.read()
|
|
321
|
-
fd.close()
|
|
322
|
-
else:
|
|
323
|
-
buffer = sys.argv[1].encode('utf-8', errors='surrogateescape')
|
|
324
|
-
# default case, read from stdin
|
|
325
|
-
else:
|
|
326
|
-
buffer = sys.stdin.buffer.read()
|
|
327
|
-
_ANSIBLE_ARGS = buffer
|
|
327
|
+
if _ANSIBLE_ARGS is None:
|
|
328
|
+
_ANSIBLE_ARGS, _ANSIBLE_PROFILE = _debugging.load_params()
|
|
328
329
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
sys.exit(1)
|
|
330
|
+
buffer = _ANSIBLE_ARGS
|
|
331
|
+
profile = _ANSIBLE_PROFILE
|
|
332
|
+
|
|
333
|
+
if not profile:
|
|
334
|
+
raise Exception("No serialization profile was specified.")
|
|
335
335
|
|
|
336
336
|
try:
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
337
|
+
decoder = _json.get_module_decoder(profile, _json.Direction.CONTROLLER_TO_MODULE)
|
|
338
|
+
params = json.loads(buffer.decode(), cls=decoder)
|
|
339
|
+
except Exception as ex:
|
|
340
|
+
raise Exception("Failed to decode JSON module parameters.") from ex
|
|
341
|
+
|
|
342
|
+
if (ansible_module_args := params.get('ANSIBLE_MODULE_ARGS', _UNSET)) is _UNSET:
|
|
343
|
+
raise Exception("ANSIBLE_MODULE_ARGS not provided.")
|
|
344
|
+
|
|
345
|
+
global _PARSED_MODULE_ARGS
|
|
346
|
+
|
|
347
|
+
_PARSED_MODULE_ARGS = copy.deepcopy(ansible_module_args) # AnsibleModule mutates the returned dict, so a copy is needed
|
|
348
|
+
|
|
349
|
+
return ansible_module_args
|
|
344
350
|
|
|
345
351
|
|
|
346
352
|
def missing_required_lib(library, reason=None, url=None):
|
|
@@ -363,13 +369,13 @@ class AnsibleModule(object):
|
|
|
363
369
|
required_one_of=None, add_file_common_args=False,
|
|
364
370
|
supports_check_mode=False, required_if=None, required_by=None):
|
|
365
371
|
|
|
366
|
-
|
|
372
|
+
"""
|
|
367
373
|
Common code for quickly building an ansible module in Python
|
|
368
374
|
(although you can write modules with anything that can return JSON).
|
|
369
375
|
|
|
370
376
|
See :ref:`developing_modules_general` for a general introduction
|
|
371
377
|
and :ref:`developing_program_flow_modules` for more detailed explanation.
|
|
372
|
-
|
|
378
|
+
"""
|
|
373
379
|
|
|
374
380
|
self._name = os.path.basename(__file__) # initialize name until we can parse from options
|
|
375
381
|
self.argument_spec = argument_spec
|
|
@@ -394,7 +400,6 @@ class AnsibleModule(object):
|
|
|
394
400
|
# run_command invocation
|
|
395
401
|
self.run_command_environ_update = {}
|
|
396
402
|
self._clean = {}
|
|
397
|
-
self._string_conversion_action = ''
|
|
398
403
|
|
|
399
404
|
self.aliases = {}
|
|
400
405
|
self._legal_inputs = []
|
|
@@ -475,9 +480,11 @@ class AnsibleModule(object):
|
|
|
475
480
|
if basedir is not None and not os.path.exists(basedir):
|
|
476
481
|
try:
|
|
477
482
|
os.makedirs(basedir, mode=0o700)
|
|
478
|
-
except
|
|
479
|
-
self.
|
|
480
|
-
|
|
483
|
+
except OSError as ex:
|
|
484
|
+
self.error_as_warning(
|
|
485
|
+
msg=f"Unable to use {basedir!r} as temporary directory, falling back to system default.",
|
|
486
|
+
exception=ex,
|
|
487
|
+
)
|
|
481
488
|
basedir = None
|
|
482
489
|
else:
|
|
483
490
|
self.warn("Module remote_tmp %s did not exist and was "
|
|
@@ -489,40 +496,80 @@ class AnsibleModule(object):
|
|
|
489
496
|
basefile = "ansible-moduletmp-%s-" % time.time()
|
|
490
497
|
try:
|
|
491
498
|
tmpdir = tempfile.mkdtemp(prefix=basefile, dir=basedir)
|
|
492
|
-
except
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
)
|
|
499
|
+
except OSError as ex:
|
|
500
|
+
raise Exception(
|
|
501
|
+
f"Failed to create remote module tmp path at dir {basedir!r} "
|
|
502
|
+
f"with prefix {basefile!r}.",
|
|
503
|
+
) from ex
|
|
497
504
|
if not self._keep_remote_files:
|
|
498
505
|
atexit.register(shutil.rmtree, tmpdir)
|
|
499
506
|
self._tmpdir = tmpdir
|
|
500
507
|
|
|
501
508
|
return self._tmpdir
|
|
502
509
|
|
|
503
|
-
def warn(
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
510
|
+
def warn(
|
|
511
|
+
self,
|
|
512
|
+
warning: str,
|
|
513
|
+
*,
|
|
514
|
+
help_text: str | None = None,
|
|
515
|
+
) -> None:
|
|
516
|
+
_skip_stackwalk = True
|
|
517
|
+
|
|
518
|
+
warn(
|
|
519
|
+
warning=warning,
|
|
520
|
+
help_text=help_text,
|
|
521
|
+
)
|
|
522
|
+
|
|
523
|
+
def error_as_warning(
|
|
524
|
+
self,
|
|
525
|
+
msg: str | None,
|
|
526
|
+
exception: BaseException,
|
|
527
|
+
*,
|
|
528
|
+
help_text: str | None = None,
|
|
529
|
+
) -> None:
|
|
530
|
+
"""Display an exception as a warning."""
|
|
531
|
+
_skip_stackwalk = True
|
|
532
|
+
|
|
533
|
+
error_as_warning(
|
|
534
|
+
msg=msg,
|
|
535
|
+
exception=exception,
|
|
536
|
+
help_text=help_text,
|
|
537
|
+
)
|
|
538
|
+
|
|
539
|
+
def deprecate(
|
|
540
|
+
self,
|
|
541
|
+
msg: str,
|
|
542
|
+
version: str | None = None,
|
|
543
|
+
date: str | None = None,
|
|
544
|
+
collection_name: str | None = None,
|
|
545
|
+
*,
|
|
546
|
+
deprecator: _messages.PluginInfo | None = None,
|
|
547
|
+
help_text: str | None = None,
|
|
548
|
+
) -> None:
|
|
549
|
+
"""
|
|
550
|
+
Record a deprecation warning to be returned with the module result.
|
|
551
|
+
Most callers do not need to provide `collection_name` or `deprecator` -- but provide only one if needed.
|
|
552
|
+
Specify `version` or `date`, but not both.
|
|
553
|
+
If `date` is a string, it must be in the form `YYYY-MM-DD`.
|
|
554
|
+
"""
|
|
555
|
+
_skip_stackwalk = True
|
|
556
|
+
|
|
557
|
+
deprecate( # pylint: disable=ansible-deprecated-date-not-permitted,ansible-deprecated-unnecessary-collection-name
|
|
558
|
+
msg=msg,
|
|
559
|
+
version=version,
|
|
560
|
+
date=date,
|
|
561
|
+
deprecator=_deprecator.get_best_deprecator(deprecator=deprecator, collection_name=collection_name),
|
|
562
|
+
help_text=help_text,
|
|
563
|
+
)
|
|
517
564
|
|
|
518
565
|
def load_file_common_arguments(self, params, path=None):
|
|
519
|
-
|
|
566
|
+
"""
|
|
520
567
|
many modules deal with files, this encapsulates common
|
|
521
568
|
options that the file module accepts such that it is directly
|
|
522
569
|
available to all modules and they can share code.
|
|
523
570
|
|
|
524
571
|
Allows to overwrite the path/dest module argument by providing path.
|
|
525
|
-
|
|
572
|
+
"""
|
|
526
573
|
|
|
527
574
|
if path is None:
|
|
528
575
|
path = params.get('path', params.get('dest', None))
|
|
@@ -613,11 +660,8 @@ class AnsibleModule(object):
|
|
|
613
660
|
return context
|
|
614
661
|
try:
|
|
615
662
|
ret = selinux.lgetfilecon_raw(to_native(path, errors='surrogate_or_strict'))
|
|
616
|
-
except OSError as
|
|
617
|
-
|
|
618
|
-
self.fail_json(path=path, msg='path %s does not exist' % path)
|
|
619
|
-
else:
|
|
620
|
-
self.fail_json(path=path, msg='failed to retrieve selinux context')
|
|
663
|
+
except OSError as ex:
|
|
664
|
+
self.fail_json(path=path, msg='Failed to retrieve selinux context.', exception=ex)
|
|
621
665
|
if ret[0] == -1:
|
|
622
666
|
return context
|
|
623
667
|
# Limit split to 4 because the selevel, the last in the list,
|
|
@@ -635,12 +679,12 @@ class AnsibleModule(object):
|
|
|
635
679
|
return (uid, gid)
|
|
636
680
|
|
|
637
681
|
def find_mount_point(self, path):
|
|
638
|
-
|
|
682
|
+
"""
|
|
639
683
|
Takes a path and returns its mount point
|
|
640
684
|
|
|
641
685
|
:param path: a string type with a filesystem path
|
|
642
686
|
:returns: the path to the mount point as a text type
|
|
643
|
-
|
|
687
|
+
"""
|
|
644
688
|
|
|
645
689
|
b_path = os.path.realpath(to_bytes(os.path.expanduser(os.path.expandvars(path)), errors='surrogate_or_strict'))
|
|
646
690
|
while not os.path.ismount(b_path):
|
|
@@ -654,9 +698,8 @@ class AnsibleModule(object):
|
|
|
654
698
|
NFS or other 'special' fs mount point, otherwise the return will be (False, None).
|
|
655
699
|
"""
|
|
656
700
|
try:
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
f.close()
|
|
701
|
+
with open('/proc/mounts', 'r') as f:
|
|
702
|
+
mount_data = f.readlines()
|
|
660
703
|
except Exception:
|
|
661
704
|
return (False, None)
|
|
662
705
|
|
|
@@ -758,9 +801,9 @@ class AnsibleModule(object):
|
|
|
758
801
|
return True
|
|
759
802
|
try:
|
|
760
803
|
os.lchown(b_path, uid, -1)
|
|
761
|
-
except
|
|
804
|
+
except OSError as ex:
|
|
762
805
|
path = to_text(b_path)
|
|
763
|
-
self.fail_json(path=path, msg='chown failed
|
|
806
|
+
self.fail_json(path=path, msg='chown failed', exception=ex)
|
|
764
807
|
changed = True
|
|
765
808
|
return changed
|
|
766
809
|
|
|
@@ -880,8 +923,7 @@ class AnsibleModule(object):
|
|
|
880
923
|
raise
|
|
881
924
|
except Exception as e:
|
|
882
925
|
path = to_text(b_path)
|
|
883
|
-
self.fail_json(path=path, msg='chmod failed', details=to_native(e)
|
|
884
|
-
exception=traceback.format_exc())
|
|
926
|
+
self.fail_json(path=path, msg='chmod failed', details=to_native(e))
|
|
885
927
|
|
|
886
928
|
path_stat = os.lstat(b_path)
|
|
887
929
|
new_mode = stat.S_IMODE(path_stat.st_mode)
|
|
@@ -929,8 +971,7 @@ class AnsibleModule(object):
|
|
|
929
971
|
if rc != 0 or err:
|
|
930
972
|
raise Exception("Error while setting attributes: %s" % (out + err))
|
|
931
973
|
except Exception as e:
|
|
932
|
-
self.fail_json(path=to_text(b_path), msg='chattr failed',
|
|
933
|
-
details=to_native(e), exception=traceback.format_exc())
|
|
974
|
+
self.fail_json(path=to_text(b_path), msg='chattr failed', details=to_native(e))
|
|
934
975
|
return changed
|
|
935
976
|
|
|
936
977
|
def get_file_attributes(self, path, include_version=True):
|
|
@@ -1115,10 +1156,10 @@ class AnsibleModule(object):
|
|
|
1115
1156
|
return self.set_fs_attributes_if_different(file_args, changed, diff, expand)
|
|
1116
1157
|
|
|
1117
1158
|
def add_path_info(self, kwargs):
|
|
1118
|
-
|
|
1159
|
+
"""
|
|
1119
1160
|
for results that are files, supplement the info about the file
|
|
1120
1161
|
in the return path with stats about the file path.
|
|
1121
|
-
|
|
1162
|
+
"""
|
|
1122
1163
|
|
|
1123
1164
|
path = kwargs.get('path', kwargs.get('dest', None))
|
|
1124
1165
|
if path is None:
|
|
@@ -1155,10 +1196,10 @@ class AnsibleModule(object):
|
|
|
1155
1196
|
return kwargs
|
|
1156
1197
|
|
|
1157
1198
|
def _check_locale(self):
|
|
1158
|
-
|
|
1199
|
+
"""
|
|
1159
1200
|
Uses the locale module to test the currently set locale
|
|
1160
1201
|
(per the LANG and LC_CTYPE environment settings)
|
|
1161
|
-
|
|
1202
|
+
"""
|
|
1162
1203
|
try:
|
|
1163
1204
|
# setting the locale to '' uses the default locale
|
|
1164
1205
|
# as it would be returned by locale.getdefaultlocale()
|
|
@@ -1175,8 +1216,7 @@ class AnsibleModule(object):
|
|
|
1175
1216
|
os.environ['LC_ALL'] = best_locale
|
|
1176
1217
|
os.environ['LC_MESSAGES'] = best_locale
|
|
1177
1218
|
except Exception as e:
|
|
1178
|
-
self.fail_json(msg="An unknown error was encountered while attempting to validate the locale: %s" %
|
|
1179
|
-
to_native(e), exception=traceback.format_exc())
|
|
1219
|
+
self.fail_json(msg="An unknown error was encountered while attempting to validate the locale: %s" % to_native(e))
|
|
1180
1220
|
|
|
1181
1221
|
def _set_internal_properties(self, argument_spec=None, module_parameters=None):
|
|
1182
1222
|
if argument_spec is None:
|
|
@@ -1206,11 +1246,11 @@ class AnsibleModule(object):
|
|
|
1206
1246
|
return safe_eval(value, locals, include_exceptions)
|
|
1207
1247
|
|
|
1208
1248
|
def _load_params(self):
|
|
1209
|
-
|
|
1249
|
+
""" read the input and set the params attribute.
|
|
1210
1250
|
|
|
1211
1251
|
This method is for backwards compatibility. The guts of the function
|
|
1212
1252
|
were moved out in 2.1 so that custom modules could read the parameters.
|
|
1213
|
-
|
|
1253
|
+
"""
|
|
1214
1254
|
# debug overrides to read args from file or cmdline
|
|
1215
1255
|
self.params = _load_params()
|
|
1216
1256
|
|
|
@@ -1226,7 +1266,6 @@ class AnsibleModule(object):
|
|
|
1226
1266
|
msg='Failed to log to syslog (%s). To proceed anyway, '
|
|
1227
1267
|
'disable syslog logging by setting no_target_syslog '
|
|
1228
1268
|
'to True in your Ansible config.' % to_native(e),
|
|
1229
|
-
exception=traceback.format_exc(),
|
|
1230
1269
|
msg_to_log=msg,
|
|
1231
1270
|
)
|
|
1232
1271
|
|
|
@@ -1290,14 +1329,14 @@ class AnsibleModule(object):
|
|
|
1290
1329
|
else:
|
|
1291
1330
|
journal.send(MESSAGE=u"%s %s" % (module, journal_msg),
|
|
1292
1331
|
**dict(journal_args))
|
|
1293
|
-
except
|
|
1332
|
+
except OSError:
|
|
1294
1333
|
# fall back to syslog since logging to journal failed
|
|
1295
1334
|
self._log_to_syslog(journal_msg)
|
|
1296
1335
|
else:
|
|
1297
1336
|
self._log_to_syslog(journal_msg)
|
|
1298
1337
|
|
|
1299
1338
|
def _log_invocation(self):
|
|
1300
|
-
|
|
1339
|
+
""" log that ansible ran the module """
|
|
1301
1340
|
# TODO: generalize a separate log function and make log_invocation use it
|
|
1302
1341
|
# Sanitize possible password argument when logging.
|
|
1303
1342
|
log_args = dict()
|
|
@@ -1350,7 +1389,7 @@ class AnsibleModule(object):
|
|
|
1350
1389
|
return None
|
|
1351
1390
|
|
|
1352
1391
|
def get_bin_path(self, arg, required=False, opt_dirs=None):
|
|
1353
|
-
|
|
1392
|
+
"""
|
|
1354
1393
|
Find system executable in PATH.
|
|
1355
1394
|
|
|
1356
1395
|
:param arg: The executable to find.
|
|
@@ -1358,7 +1397,7 @@ class AnsibleModule(object):
|
|
|
1358
1397
|
:param opt_dirs: optional list of directories to search in addition to ``PATH``
|
|
1359
1398
|
:returns: if found return full path; otherwise return original arg, unless 'warning' then return None
|
|
1360
1399
|
:raises: Sysexit: if arg is not found and required=True (via fail_json)
|
|
1361
|
-
|
|
1400
|
+
"""
|
|
1362
1401
|
|
|
1363
1402
|
bin_path = None
|
|
1364
1403
|
try:
|
|
@@ -1370,7 +1409,7 @@ class AnsibleModule(object):
|
|
|
1370
1409
|
return bin_path
|
|
1371
1410
|
|
|
1372
1411
|
def boolean(self, arg):
|
|
1373
|
-
|
|
1412
|
+
"""Convert the argument to a boolean"""
|
|
1374
1413
|
if arg is None:
|
|
1375
1414
|
return arg
|
|
1376
1415
|
|
|
@@ -1380,8 +1419,15 @@ class AnsibleModule(object):
|
|
|
1380
1419
|
self.fail_json(msg=to_native(e))
|
|
1381
1420
|
|
|
1382
1421
|
def jsonify(self, data):
|
|
1422
|
+
# deprecated: description='deprecate AnsibleModule.jsonify()' core_version='2.23'
|
|
1423
|
+
# deprecate(
|
|
1424
|
+
# msg="The `AnsibleModule.jsonify' method is deprecated.",
|
|
1425
|
+
# version="2.27",
|
|
1426
|
+
# # help_text="", # DTFIX-FUTURE: fill in this help text
|
|
1427
|
+
# )
|
|
1428
|
+
|
|
1383
1429
|
try:
|
|
1384
|
-
return
|
|
1430
|
+
return json.dumps(data, cls=_common_json._get_legacy_encoder())
|
|
1385
1431
|
except UnicodeError as e:
|
|
1386
1432
|
self.fail_json(msg=to_text(e))
|
|
1387
1433
|
|
|
@@ -1397,6 +1443,7 @@ class AnsibleModule(object):
|
|
|
1397
1443
|
self.cleanup(path)
|
|
1398
1444
|
|
|
1399
1445
|
def _return_formatted(self, kwargs):
|
|
1446
|
+
_skip_stackwalk = True
|
|
1400
1447
|
|
|
1401
1448
|
self.add_path_info(kwargs)
|
|
1402
1449
|
|
|
@@ -1404,39 +1451,63 @@ class AnsibleModule(object):
|
|
|
1404
1451
|
kwargs['invocation'] = {'module_args': self.params}
|
|
1405
1452
|
|
|
1406
1453
|
if 'warnings' in kwargs:
|
|
1454
|
+
self.deprecate( # pylint: disable=ansible-deprecated-unnecessary-collection-name
|
|
1455
|
+
msg='Passing `warnings` to `exit_json` or `fail_json` is deprecated.',
|
|
1456
|
+
version='2.23',
|
|
1457
|
+
help_text='Use `AnsibleModule.warn` instead.',
|
|
1458
|
+
deprecator=_deprecator.ANSIBLE_CORE_DEPRECATOR,
|
|
1459
|
+
)
|
|
1460
|
+
|
|
1407
1461
|
if isinstance(kwargs['warnings'], list):
|
|
1408
1462
|
for w in kwargs['warnings']:
|
|
1409
1463
|
self.warn(w)
|
|
1410
1464
|
else:
|
|
1411
1465
|
self.warn(kwargs['warnings'])
|
|
1412
1466
|
|
|
1413
|
-
warnings =
|
|
1467
|
+
warnings = get_warnings()
|
|
1414
1468
|
if warnings:
|
|
1415
1469
|
kwargs['warnings'] = warnings
|
|
1416
1470
|
|
|
1417
1471
|
if 'deprecations' in kwargs:
|
|
1472
|
+
self.deprecate( # pylint: disable=ansible-deprecated-unnecessary-collection-name
|
|
1473
|
+
msg='Passing `deprecations` to `exit_json` or `fail_json` is deprecated.',
|
|
1474
|
+
version='2.23',
|
|
1475
|
+
help_text='Use `AnsibleModule.deprecate` instead.',
|
|
1476
|
+
deprecator=_deprecator.ANSIBLE_CORE_DEPRECATOR,
|
|
1477
|
+
)
|
|
1478
|
+
|
|
1418
1479
|
if isinstance(kwargs['deprecations'], list):
|
|
1419
1480
|
for d in kwargs['deprecations']:
|
|
1420
|
-
if isinstance(d,
|
|
1421
|
-
self.deprecate(
|
|
1481
|
+
if isinstance(d, (KeysView, Sequence)) and len(d) == 2:
|
|
1482
|
+
self.deprecate( # pylint: disable=ansible-deprecated-unnecessary-collection-name,ansible-invalid-deprecated-version
|
|
1483
|
+
msg=d[0],
|
|
1484
|
+
version=d[1],
|
|
1485
|
+
deprecator=_deprecator.get_best_deprecator(),
|
|
1486
|
+
)
|
|
1422
1487
|
elif isinstance(d, Mapping):
|
|
1423
|
-
self.deprecate(
|
|
1424
|
-
|
|
1488
|
+
self.deprecate( # pylint: disable=ansible-deprecated-date-not-permitted,ansible-deprecated-unnecessary-collection-name
|
|
1489
|
+
msg=d['msg'],
|
|
1490
|
+
version=d.get('version'),
|
|
1491
|
+
date=d.get('date'),
|
|
1492
|
+
deprecator=_deprecator.get_best_deprecator(collection_name=d.get('collection_name')),
|
|
1493
|
+
)
|
|
1425
1494
|
else:
|
|
1426
|
-
self.deprecate(
|
|
1495
|
+
self.deprecate( # pylint: disable=ansible-deprecated-unnecessary-collection-name,ansible-deprecated-no-version
|
|
1496
|
+
msg=d,
|
|
1497
|
+
deprecator=_deprecator.get_best_deprecator(),
|
|
1498
|
+
)
|
|
1427
1499
|
else:
|
|
1428
|
-
self.deprecate(
|
|
1500
|
+
self.deprecate( # pylint: disable=ansible-deprecated-unnecessary-collection-name,ansible-deprecated-no-version
|
|
1501
|
+
msg=kwargs['deprecations'],
|
|
1502
|
+
deprecator=_deprecator.get_best_deprecator(),
|
|
1503
|
+
)
|
|
1429
1504
|
|
|
1430
|
-
deprecations =
|
|
1505
|
+
deprecations = get_deprecations()
|
|
1431
1506
|
if deprecations:
|
|
1432
1507
|
kwargs['deprecations'] = deprecations
|
|
1433
1508
|
|
|
1434
1509
|
# preserve bools/none from no_log
|
|
1435
|
-
|
|
1436
|
-
preserved = {}
|
|
1437
|
-
for k, v in kwargs.items():
|
|
1438
|
-
if v is None or isinstance(v, bool):
|
|
1439
|
-
preserved[k] = v
|
|
1510
|
+
preserved = {k: v for k, v in kwargs.items() if v is None or isinstance(v, bool)}
|
|
1440
1511
|
|
|
1441
1512
|
# strip no_log collisions
|
|
1442
1513
|
kwargs = remove_values(kwargs, self.no_log_values)
|
|
@@ -1444,28 +1515,78 @@ class AnsibleModule(object):
|
|
|
1444
1515
|
# return preserved
|
|
1445
1516
|
kwargs.update(preserved)
|
|
1446
1517
|
|
|
1447
|
-
|
|
1518
|
+
encoder = _json.get_module_encoder(_ANSIBLE_PROFILE, _json.Direction.MODULE_TO_CONTROLLER)
|
|
1519
|
+
print('\n%s' % json.dumps(kwargs, cls=encoder))
|
|
1448
1520
|
|
|
1449
|
-
def exit_json(self, **kwargs):
|
|
1450
|
-
|
|
1521
|
+
def exit_json(self, **kwargs) -> t.NoReturn:
|
|
1522
|
+
""" return from the module, without error """
|
|
1523
|
+
_skip_stackwalk = True
|
|
1451
1524
|
|
|
1452
1525
|
self.do_cleanup_files()
|
|
1453
1526
|
self._return_formatted(kwargs)
|
|
1454
1527
|
sys.exit(0)
|
|
1455
1528
|
|
|
1456
|
-
def fail_json(self, msg, **kwargs):
|
|
1457
|
-
|
|
1529
|
+
def fail_json(self, msg: str, *, exception: BaseException | str | None = _UNSET, **kwargs) -> t.NoReturn:
|
|
1530
|
+
"""
|
|
1531
|
+
Return from the module with an error message and optional exception/traceback detail.
|
|
1532
|
+
A traceback will only be included in the result if error traceback capturing has been enabled.
|
|
1533
|
+
|
|
1534
|
+
When `exception` is an exception object, its message chain will be automatically combined with `msg` to create the final error message.
|
|
1535
|
+
The message chain includes the exception's message as well as messages from any __cause__ exceptions.
|
|
1536
|
+
The traceback from `exception` will be used for the formatted traceback.
|
|
1537
|
+
|
|
1538
|
+
When `exception` is a string, it will be used as the formatted traceback.
|
|
1539
|
+
|
|
1540
|
+
When `exception` is set to `None`, the current call stack will be used for the formatted traceback.
|
|
1541
|
+
|
|
1542
|
+
When `exception` is not specified, a formatted traceback will be retrieved from the current exception.
|
|
1543
|
+
If no exception is pending, the current call stack will be used instead.
|
|
1544
|
+
"""
|
|
1545
|
+
_skip_stackwalk = True
|
|
1546
|
+
|
|
1547
|
+
msg = str(msg) # coerce to str instead of raising an error due to an invalid type
|
|
1458
1548
|
|
|
1459
|
-
kwargs
|
|
1460
|
-
|
|
1549
|
+
kwargs.update(
|
|
1550
|
+
failed=True,
|
|
1551
|
+
msg=msg,
|
|
1552
|
+
)
|
|
1461
1553
|
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1554
|
+
if isinstance(exception, BaseException):
|
|
1555
|
+
# Include a `_messages.Event` in the result.
|
|
1556
|
+
# The `msg` is included in the chain to ensure it is not lost when looking only at `exception` from the result.
|
|
1557
|
+
|
|
1558
|
+
kwargs.update(
|
|
1559
|
+
exception=_messages.ErrorSummary(
|
|
1560
|
+
event=_messages.Event(
|
|
1561
|
+
msg=msg,
|
|
1562
|
+
formatted_traceback=_traceback.maybe_capture_traceback(msg, _traceback.TracebackEvent.ERROR),
|
|
1563
|
+
chain=_messages.EventChain(
|
|
1564
|
+
msg_reason=_errors.MSG_REASON_DIRECT_CAUSE,
|
|
1565
|
+
traceback_reason="The above exception was the direct cause of the following error:",
|
|
1566
|
+
event=_errors.EventFactory.from_exception(exception, _traceback.is_traceback_enabled(_traceback.TracebackEvent.ERROR)),
|
|
1567
|
+
),
|
|
1568
|
+
),
|
|
1569
|
+
),
|
|
1570
|
+
)
|
|
1571
|
+
elif _traceback.is_traceback_enabled(_traceback.TracebackEvent.ERROR):
|
|
1572
|
+
# Include only a formatted traceback string in the result.
|
|
1573
|
+
# The controller will combine this with `msg` to create an `_messages.ErrorSummary`.
|
|
1574
|
+
|
|
1575
|
+
formatted_traceback: str | None
|
|
1576
|
+
|
|
1577
|
+
if isinstance(exception, str):
|
|
1578
|
+
formatted_traceback = exception
|
|
1579
|
+
elif exception is _UNSET and (current_exception := t.cast(t.Optional[BaseException], sys.exc_info()[1])):
|
|
1580
|
+
formatted_traceback = _traceback.maybe_extract_traceback(current_exception, _traceback.TracebackEvent.ERROR)
|
|
1581
|
+
else:
|
|
1582
|
+
formatted_traceback = _traceback.maybe_capture_traceback(msg, _traceback.TracebackEvent.ERROR)
|
|
1583
|
+
|
|
1584
|
+
if formatted_traceback:
|
|
1585
|
+
kwargs.update(exception=formatted_traceback)
|
|
1466
1586
|
|
|
1467
1587
|
self.do_cleanup_files()
|
|
1468
1588
|
self._return_formatted(kwargs)
|
|
1589
|
+
|
|
1469
1590
|
sys.exit(1)
|
|
1470
1591
|
|
|
1471
1592
|
def fail_on_missing_params(self, required_params=None):
|
|
@@ -1477,7 +1598,7 @@ class AnsibleModule(object):
|
|
|
1477
1598
|
self.fail_json(msg=to_native(e))
|
|
1478
1599
|
|
|
1479
1600
|
def digest_from_file(self, filename, algorithm):
|
|
1480
|
-
|
|
1601
|
+
""" Return hex digest of local file for a digest_method specified by name, or None if file is not present. """
|
|
1481
1602
|
b_filename = to_bytes(filename, errors='surrogate_or_strict')
|
|
1482
1603
|
|
|
1483
1604
|
if not os.path.exists(b_filename):
|
|
@@ -1505,7 +1626,7 @@ class AnsibleModule(object):
|
|
|
1505
1626
|
return digest_method.hexdigest()
|
|
1506
1627
|
|
|
1507
1628
|
def md5(self, filename):
|
|
1508
|
-
|
|
1629
|
+
""" Return MD5 hex digest of local file using digest_from_file().
|
|
1509
1630
|
|
|
1510
1631
|
Do not use this function unless you have no other choice for:
|
|
1511
1632
|
1) Optional backwards compatibility
|
|
@@ -1514,21 +1635,21 @@ class AnsibleModule(object):
|
|
|
1514
1635
|
This function will not work on systems complying with FIPS-140-2.
|
|
1515
1636
|
|
|
1516
1637
|
Most uses of this function can use the module.sha1 function instead.
|
|
1517
|
-
|
|
1638
|
+
"""
|
|
1518
1639
|
if 'md5' not in AVAILABLE_HASH_ALGORITHMS:
|
|
1519
1640
|
raise ValueError('MD5 not available. Possibly running in FIPS mode')
|
|
1520
1641
|
return self.digest_from_file(filename, 'md5')
|
|
1521
1642
|
|
|
1522
1643
|
def sha1(self, filename):
|
|
1523
|
-
|
|
1644
|
+
""" Return SHA1 hex digest of local file using digest_from_file(). """
|
|
1524
1645
|
return self.digest_from_file(filename, 'sha1')
|
|
1525
1646
|
|
|
1526
1647
|
def sha256(self, filename):
|
|
1527
|
-
|
|
1648
|
+
""" Return SHA-256 hex digest of local file using digest_from_file(). """
|
|
1528
1649
|
return self.digest_from_file(filename, 'sha256')
|
|
1529
1650
|
|
|
1530
1651
|
def backup_local(self, fn):
|
|
1531
|
-
|
|
1652
|
+
"""make a date-marked backup of the specified file, return True or False on success or failure"""
|
|
1532
1653
|
|
|
1533
1654
|
backupdest = ''
|
|
1534
1655
|
if os.path.exists(fn):
|
|
@@ -1536,10 +1657,11 @@ class AnsibleModule(object):
|
|
|
1536
1657
|
ext = time.strftime("%Y-%m-%d@%H:%M:%S~", time.localtime(time.time()))
|
|
1537
1658
|
backupdest = '%s.%s.%s' % (fn, os.getpid(), ext)
|
|
1538
1659
|
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1660
|
+
if not self.check_mode:
|
|
1661
|
+
try:
|
|
1662
|
+
self.preserved_copy(fn, backupdest)
|
|
1663
|
+
except (shutil.Error, IOError) as ex:
|
|
1664
|
+
raise Exception(f'Could not make backup of {fn!r} to {backupdest!r}.') from ex
|
|
1543
1665
|
|
|
1544
1666
|
return backupdest
|
|
1545
1667
|
|
|
@@ -1586,9 +1708,9 @@ class AnsibleModule(object):
|
|
|
1586
1708
|
self.set_attributes_if_different(dest, current_attribs, True)
|
|
1587
1709
|
|
|
1588
1710
|
def atomic_move(self, src, dest, unsafe_writes=False, keep_dest_attrs=True):
|
|
1589
|
-
|
|
1711
|
+
"""atomically move src to dest, copying attributes from dest, returns true on success
|
|
1590
1712
|
it uses os.rename to ensure this as it is an atomic operation, rest of the function is
|
|
1591
|
-
to work around limitations, corner cases and ensure selinux context is saved if possible
|
|
1713
|
+
to work around limitations, corner cases and ensure selinux context is saved if possible"""
|
|
1592
1714
|
context = None
|
|
1593
1715
|
dest_stat = None
|
|
1594
1716
|
b_src = to_bytes(src, errors='surrogate_or_strict')
|
|
@@ -1613,29 +1735,25 @@ class AnsibleModule(object):
|
|
|
1613
1735
|
try:
|
|
1614
1736
|
# Optimistically try a rename, solves some corner cases and can avoid useless work, throws exception if not atomic.
|
|
1615
1737
|
os.rename(b_src, b_dest)
|
|
1616
|
-
except
|
|
1617
|
-
if
|
|
1738
|
+
except OSError as ex:
|
|
1739
|
+
if ex.errno in (errno.EPERM, errno.EXDEV, errno.EACCES, errno.ETXTBSY, errno.EBUSY):
|
|
1618
1740
|
# only try workarounds for errno 18 (cross device), 1 (not permitted), 13 (permission denied)
|
|
1619
1741
|
# and 26 (text file busy) which happens on vagrant synced folders and other 'exotic' non posix file systems
|
|
1620
|
-
self.fail_json(msg='Could not replace file: %s to %s: %s' % (src, dest, to_native(e)), exception=traceback.format_exc())
|
|
1621
|
-
else:
|
|
1622
1742
|
# Use bytes here. In the shippable CI, this fails with
|
|
1623
1743
|
# a UnicodeError with surrogateescape'd strings for an unknown
|
|
1624
1744
|
# reason (doesn't happen in a local Ubuntu16.04 VM)
|
|
1625
1745
|
b_dest_dir = os.path.dirname(b_dest)
|
|
1626
1746
|
b_suffix = os.path.basename(b_dest)
|
|
1627
|
-
error_msg = None
|
|
1628
1747
|
tmp_dest_name = None
|
|
1629
1748
|
try:
|
|
1630
1749
|
tmp_dest_fd, tmp_dest_name = tempfile.mkstemp(prefix=b'.ansible_tmp', dir=b_dest_dir, suffix=b_suffix)
|
|
1631
|
-
except
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
self.fail_json(msg=error_msg, exception=traceback.format_exc())
|
|
1750
|
+
except OSError as ex:
|
|
1751
|
+
if unsafe_writes:
|
|
1752
|
+
self._unsafe_writes(b_src, b_dest)
|
|
1753
|
+
else:
|
|
1754
|
+
raise Exception(
|
|
1755
|
+
f'The destination directory {os.path.dirname(dest)!r} is not writable by the current user.'
|
|
1756
|
+
) from ex
|
|
1639
1757
|
|
|
1640
1758
|
if tmp_dest_name:
|
|
1641
1759
|
b_tmp_dest_name = to_bytes(tmp_dest_name, errors='surrogate_or_strict')
|
|
@@ -1664,24 +1782,27 @@ class AnsibleModule(object):
|
|
|
1664
1782
|
if dest_stat and (tmp_stat.st_uid != dest_stat.st_uid or tmp_stat.st_gid != dest_stat.st_gid):
|
|
1665
1783
|
os.chown(b_tmp_dest_name, dest_stat.st_uid, dest_stat.st_gid)
|
|
1666
1784
|
os.utime(b_tmp_dest_name, times=(time.time(), time.time()))
|
|
1667
|
-
except OSError as
|
|
1668
|
-
if
|
|
1785
|
+
except OSError as ex:
|
|
1786
|
+
if ex.errno != errno.EPERM:
|
|
1669
1787
|
raise
|
|
1670
1788
|
try:
|
|
1671
1789
|
os.rename(b_tmp_dest_name, b_dest)
|
|
1672
|
-
except (shutil.Error, OSError
|
|
1673
|
-
if unsafe_writes and
|
|
1790
|
+
except (shutil.Error, OSError) as ex:
|
|
1791
|
+
if unsafe_writes and ex.errno == errno.EBUSY:
|
|
1674
1792
|
self._unsafe_writes(b_tmp_dest_name, b_dest)
|
|
1675
1793
|
else:
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1794
|
+
raise Exception(
|
|
1795
|
+
f'Unable to make {src!r} into to {dest!r}, failed final rename from {to_text(b_tmp_dest_name)!r}.'
|
|
1796
|
+
) from ex
|
|
1797
|
+
except (shutil.Error, OSError) as ex:
|
|
1679
1798
|
if unsafe_writes:
|
|
1680
1799
|
self._unsafe_writes(b_src, b_dest)
|
|
1681
1800
|
else:
|
|
1682
|
-
|
|
1801
|
+
raise Exception(f'Failed to replace {dest!r} with {src!r}.') from ex
|
|
1683
1802
|
finally:
|
|
1684
1803
|
self.cleanup(b_tmp_dest_name)
|
|
1804
|
+
else:
|
|
1805
|
+
raise Exception(f'Could not replace {dest!r} with {src!r}.') from ex
|
|
1685
1806
|
|
|
1686
1807
|
if creating:
|
|
1687
1808
|
# make sure the file has the correct permissions
|
|
@@ -1708,19 +1829,11 @@ class AnsibleModule(object):
|
|
|
1708
1829
|
# sadly there are some situations where we cannot ensure atomicity, but only if
|
|
1709
1830
|
# the user insists and we get the appropriate error we update the file unsafely
|
|
1710
1831
|
try:
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
finally: # assuring closed files in 2.4 compatible way
|
|
1717
|
-
if out_dest:
|
|
1718
|
-
out_dest.close()
|
|
1719
|
-
if in_src:
|
|
1720
|
-
in_src.close()
|
|
1721
|
-
except (shutil.Error, OSError, IOError) as e:
|
|
1722
|
-
self.fail_json(msg='Could not write data to file (%s) from (%s): %s' % (dest, src, to_native(e)),
|
|
1723
|
-
exception=traceback.format_exc())
|
|
1832
|
+
with open(dest, 'wb') as out_dest:
|
|
1833
|
+
with open(src, 'rb') as in_src:
|
|
1834
|
+
shutil.copyfileobj(in_src, out_dest)
|
|
1835
|
+
except (shutil.Error, OSError) as ex:
|
|
1836
|
+
raise Exception(f'Could not write data to file {dest!r} from {src!r}.') from ex
|
|
1724
1837
|
|
|
1725
1838
|
def _clean_args(self, args):
|
|
1726
1839
|
|
|
@@ -1756,7 +1869,7 @@ class AnsibleModule(object):
|
|
|
1756
1869
|
def run_command(self, args, check_rc=False, close_fds=True, executable=None, data=None, binary_data=False, path_prefix=None, cwd=None,
|
|
1757
1870
|
use_unsafe_shell=False, prompt_regex=None, environ_update=None, umask=None, encoding='utf-8', errors='surrogate_or_strict',
|
|
1758
1871
|
expand_user_and_vars=True, pass_fds=None, before_communicate_callback=None, ignore_invalid_cwd=True, handle_exceptions=True):
|
|
1759
|
-
|
|
1872
|
+
"""
|
|
1760
1873
|
Execute a command, returns rc, stdout, and stderr.
|
|
1761
1874
|
|
|
1762
1875
|
The mechanism of this method for reading stdout and stderr differs from
|
|
@@ -1787,18 +1900,18 @@ class AnsibleModule(object):
|
|
|
1787
1900
|
the execution to hang (especially if no input data is specified)
|
|
1788
1901
|
:kw environ_update: dictionary to *update* environ variables with
|
|
1789
1902
|
:kw umask: Umask to be used when running the command. Default None
|
|
1790
|
-
:kw encoding: Since we return
|
|
1903
|
+
:kw encoding: Since we return strings, we need to
|
|
1791
1904
|
know the encoding to use to transform from bytes to text. If you
|
|
1792
1905
|
want to always get bytes back, use encoding=None. The default is
|
|
1793
1906
|
"utf-8". This does not affect transformation of strings given as
|
|
1794
1907
|
args.
|
|
1795
|
-
:kw errors: Since we return
|
|
1908
|
+
:kw errors: Since we return strings, we need to
|
|
1796
1909
|
transform stdout and stderr from bytes to text. If the bytes are
|
|
1797
1910
|
undecodable in the ``encoding`` specified, then use this error
|
|
1798
1911
|
handler to deal with them. The default is ``surrogate_or_strict``
|
|
1799
1912
|
which means that the bytes will be decoded using the
|
|
1800
1913
|
surrogateescape error handler if available (available on all
|
|
1801
|
-
|
|
1914
|
+
Python versions we support) otherwise a UnicodeError traceback
|
|
1802
1915
|
will be raised. This does not affect transformations of strings
|
|
1803
1916
|
given as args.
|
|
1804
1917
|
:kw expand_user_and_vars: When ``use_unsafe_shell=False`` this argument
|
|
@@ -1806,10 +1919,8 @@ class AnsibleModule(object):
|
|
|
1806
1919
|
are expanded before running the command. When ``True`` a string such as
|
|
1807
1920
|
``$SHELL`` will be expanded regardless of escaping. When ``False`` and
|
|
1808
1921
|
``use_unsafe_shell=False`` no path or variable expansion will be done.
|
|
1809
|
-
:kw pass_fds:
|
|
1810
|
-
|
|
1811
|
-
to an underlying ``Popen`` constructor. On Python 2, this will
|
|
1812
|
-
set ``close_fds`` to False.
|
|
1922
|
+
:kw pass_fds: This argument dictates which file descriptors should be passed
|
|
1923
|
+
to an underlying ``Popen`` constructor.
|
|
1813
1924
|
:kw before_communicate_callback: This function will be called
|
|
1814
1925
|
after ``Popen`` object will be created
|
|
1815
1926
|
but before communicating to the process.
|
|
@@ -1820,12 +1931,11 @@ class AnsibleModule(object):
|
|
|
1820
1931
|
:kw handle_exceptions: This flag indicates whether an exception will
|
|
1821
1932
|
be handled inline and issue a failed_json or if the caller should
|
|
1822
1933
|
handle it.
|
|
1823
|
-
:returns: A 3-tuple of return code (
|
|
1824
|
-
and stderr
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
'''
|
|
1934
|
+
:returns: A 3-tuple of return code (int), stdout (str), and stderr (str).
|
|
1935
|
+
stdout and stderr are text strings converted according to the encoding
|
|
1936
|
+
and errors parameters. If you want byte strings, use encoding=None
|
|
1937
|
+
to turn decoding to text off.
|
|
1938
|
+
"""
|
|
1829
1939
|
# used by clean args later on
|
|
1830
1940
|
self._clean = None
|
|
1831
1941
|
|
|
@@ -2006,18 +2116,16 @@ class AnsibleModule(object):
|
|
|
2006
2116
|
selector.close()
|
|
2007
2117
|
|
|
2008
2118
|
rc = cmd.returncode
|
|
2009
|
-
except
|
|
2010
|
-
self.log("Error Executing CMD:%s Exception:%s" % (self._clean_args(args), to_native(e)))
|
|
2119
|
+
except OSError as ex:
|
|
2011
2120
|
if handle_exceptions:
|
|
2012
|
-
self.fail_json(rc=
|
|
2121
|
+
self.fail_json(rc=ex.errno, stdout='', stderr='', msg="Error executing command.", cmd=self._clean_args(args), exception=ex)
|
|
2013
2122
|
else:
|
|
2014
|
-
raise
|
|
2015
|
-
except Exception as
|
|
2016
|
-
self.log("Error Executing CMD:%s Exception:%s" % (self._clean_args(args), to_native(traceback.format_exc())))
|
|
2123
|
+
raise
|
|
2124
|
+
except Exception as ex:
|
|
2017
2125
|
if handle_exceptions:
|
|
2018
|
-
self.fail_json(rc=257, stdout=
|
|
2126
|
+
self.fail_json(rc=257, stdout='', stderr='', msg="Error executing command.", cmd=self._clean_args(args), exception=ex)
|
|
2019
2127
|
else:
|
|
2020
|
-
raise
|
|
2128
|
+
raise
|
|
2021
2129
|
|
|
2022
2130
|
if rc != 0 and check_rc:
|
|
2023
2131
|
msg = heuristic_log_sanitize(stderr.rstrip(), self.no_log_values)
|
|
@@ -2031,9 +2139,8 @@ class AnsibleModule(object):
|
|
|
2031
2139
|
|
|
2032
2140
|
def append_to_file(self, filename, str):
|
|
2033
2141
|
filename = os.path.expandvars(os.path.expanduser(filename))
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
fh.close()
|
|
2142
|
+
with open(filename, 'a') as fh:
|
|
2143
|
+
fh.write(str)
|
|
2037
2144
|
|
|
2038
2145
|
def bytes_to_human(self, size):
|
|
2039
2146
|
return bytes_to_human(size)
|
|
@@ -2072,13 +2179,7 @@ def get_module_path():
|
|
|
2072
2179
|
|
|
2073
2180
|
def __getattr__(importable_name):
|
|
2074
2181
|
"""Inject import-time deprecation warnings."""
|
|
2075
|
-
if importable_name == '
|
|
2076
|
-
from ansible.module_utils.pycompat24 import get_exception
|
|
2077
|
-
importable = get_exception
|
|
2078
|
-
elif importable_name in {'literal_eval', '_literal_eval'}:
|
|
2079
|
-
from ast import literal_eval
|
|
2080
|
-
importable = literal_eval
|
|
2081
|
-
elif importable_name == 'datetime':
|
|
2182
|
+
if importable_name == 'datetime':
|
|
2082
2183
|
import datetime
|
|
2083
2184
|
importable = datetime
|
|
2084
2185
|
elif importable_name == 'signal':
|
|
@@ -2095,7 +2196,7 @@ def __getattr__(importable_name):
|
|
|
2095
2196
|
importable = repeat
|
|
2096
2197
|
elif importable_name in {
|
|
2097
2198
|
'PY2', 'PY3', 'b', 'binary_type', 'integer_types',
|
|
2098
|
-
'iteritems', 'string_types', '
|
|
2199
|
+
'iteritems', 'string_types', 'text_type',
|
|
2099
2200
|
}:
|
|
2100
2201
|
import importlib
|
|
2101
2202
|
importable = getattr(
|