ansible-core 2.18.7rc1__py3-none-any.whl → 2.19.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ansible-core might be problematic. Click here for more details.
- ansible/_internal/__init__.py +53 -0
- ansible/_internal/_ansiballz/__init__.py +0 -0
- ansible/_internal/_ansiballz/_builder.py +101 -0
- ansible/_internal/_ansiballz/_wrapper.py +262 -0
- ansible/_internal/_collection_proxy.py +47 -0
- ansible/_internal/_datatag/__init__.py +0 -0
- ansible/_internal/_datatag/_tags.py +130 -0
- ansible/_internal/_datatag/_utils.py +19 -0
- ansible/_internal/_datatag/_wrappers.py +33 -0
- ansible/_internal/_errors/__init__.py +0 -0
- ansible/_internal/_errors/_alarm_timeout.py +66 -0
- ansible/_internal/_errors/_captured.py +123 -0
- ansible/_internal/_errors/_error_factory.py +89 -0
- ansible/_internal/_errors/_error_utils.py +240 -0
- ansible/_internal/_errors/_handler.py +91 -0
- ansible/_internal/_errors/_task_timeout.py +28 -0
- ansible/_internal/_event_formatting.py +127 -0
- ansible/_internal/_json/__init__.py +214 -0
- ansible/_internal/_json/_legacy_encoder.py +34 -0
- ansible/_internal/_json/_profiles/__init__.py +0 -0
- ansible/_internal/_json/_profiles/_cache_persistence.py +57 -0
- ansible/_internal/_json/_profiles/_inventory_legacy.py +40 -0
- ansible/_internal/_json/_profiles/_legacy.py +189 -0
- ansible/_internal/_locking.py +21 -0
- ansible/_internal/_plugins/__init__.py +0 -0
- ansible/_internal/_plugins/_cache.py +57 -0
- ansible/_internal/_ssh/__init__.py +0 -0
- ansible/_internal/_ssh/_agent_launch.py +91 -0
- ansible/_internal/_ssh/_ssh_agent.py +619 -0
- ansible/_internal/_task.py +78 -0
- ansible/_internal/_templating/__init__.py +12 -0
- ansible/_internal/_templating/_access.py +86 -0
- ansible/_internal/_templating/_chain_templar.py +63 -0
- ansible/_internal/_templating/_datatag.py +95 -0
- ansible/_internal/_templating/_engine.py +592 -0
- ansible/_internal/_templating/_errors.py +28 -0
- ansible/_internal/_templating/_jinja_bits.py +1106 -0
- ansible/_internal/_templating/_jinja_common.py +323 -0
- ansible/_internal/_templating/_jinja_patches.py +44 -0
- ansible/_internal/_templating/_jinja_plugins.py +375 -0
- ansible/_internal/_templating/_lazy_containers.py +633 -0
- ansible/_internal/_templating/_marker_behaviors.py +103 -0
- ansible/_internal/_templating/_template_vars.py +72 -0
- ansible/_internal/_templating/_transform.py +70 -0
- ansible/_internal/_templating/_utils.py +108 -0
- ansible/_internal/_testing.py +26 -0
- ansible/_internal/_wrapt.py +1052 -0
- ansible/_internal/_yaml/__init__.py +0 -0
- ansible/_internal/_yaml/_constructor.py +240 -0
- ansible/_internal/_yaml/_dumper.py +70 -0
- ansible/_internal/_yaml/_errors.py +166 -0
- ansible/_internal/_yaml/_loader.py +66 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/README.md +11 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/action/debug.py +36 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/apply_trust.py +19 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/dump_object.py +27 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/finalize.py +16 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/origin.py +18 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/python_literal_eval.py +24 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/python_literal_eval.yml +33 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/tag_names.py +16 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/true_type.py +17 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/unmask.py +49 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/lookup/config.py +21 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/lookup/config.yml +2 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged.py +15 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged.yml +19 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged_with.py +18 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged_with.yml +19 -0
- ansible/cli/__init__.py +93 -104
- ansible/cli/_ssh_askpass.py +54 -0
- ansible/cli/adhoc.py +20 -10
- ansible/cli/arguments/option_helpers.py +163 -10
- ansible/cli/config.py +43 -68
- ansible/cli/console.py +13 -11
- ansible/cli/doc.py +134 -77
- ansible/cli/galaxy.py +27 -20
- ansible/cli/inventory.py +28 -28
- ansible/cli/playbook.py +4 -12
- ansible/cli/pull.py +6 -3
- ansible/cli/scripts/ansible_connection_cli_stub.py +7 -7
- ansible/cli/vault.py +12 -11
- ansible/compat/__init__.py +2 -2
- ansible/compat/importlib_resources.py +9 -12
- ansible/config/base.yml +218 -133
- ansible/config/manager.py +220 -159
- ansible/constants.py +2 -65
- ansible/errors/__init__.py +350 -256
- ansible/executor/interpreter_discovery.py +28 -149
- ansible/executor/module_common.py +480 -514
- ansible/executor/play_iterator.py +22 -27
- ansible/executor/playbook_executor.py +11 -11
- ansible/executor/powershell/async_watchdog.ps1 +97 -102
- ansible/executor/powershell/async_wrapper.ps1 +204 -153
- ansible/executor/powershell/become_wrapper.ps1 +107 -144
- ansible/executor/powershell/bootstrap_wrapper.ps1 +46 -9
- ansible/executor/powershell/coverage_wrapper.ps1 +91 -135
- ansible/executor/powershell/exec_wrapper.ps1 +675 -196
- ansible/executor/powershell/module_manifest.py +469 -265
- ansible/executor/powershell/module_wrapper.ps1 +195 -186
- ansible/executor/powershell/powershell_expand_user.ps1 +20 -0
- ansible/executor/powershell/powershell_mkdtemp.ps1 +17 -0
- ansible/executor/powershell/psrp_fetch_file.ps1 +41 -0
- ansible/executor/powershell/psrp_put_file.ps1 +122 -0
- ansible/executor/powershell/winrm_fetch_file.ps1 +46 -0
- ansible/executor/powershell/winrm_put_file.ps1 +36 -0
- ansible/executor/process/worker.py +139 -149
- ansible/executor/stats.py +5 -5
- ansible/executor/task_executor.py +270 -297
- ansible/executor/task_queue_manager.py +135 -137
- ansible/executor/task_result.py +182 -79
- ansible/galaxy/__init__.py +2 -2
- ansible/galaxy/api.py +26 -25
- ansible/galaxy/collection/__init__.py +6 -14
- ansible/galaxy/collection/concrete_artifact_manager.py +12 -21
- ansible/galaxy/dependency_resolution/dataclasses.py +14 -4
- ansible/galaxy/dependency_resolution/providers.py +4 -4
- ansible/galaxy/dependency_resolution/reporters.py +81 -0
- ansible/galaxy/role.py +6 -10
- ansible/galaxy/token.py +28 -21
- ansible/inventory/data.py +47 -57
- ansible/inventory/group.py +50 -73
- ansible/inventory/helpers.py +9 -0
- ansible/inventory/host.py +37 -54
- ansible/inventory/manager.py +79 -34
- ansible/keyword_desc.yml +1 -1
- ansible/module_utils/_internal/__init__.py +55 -0
- ansible/module_utils/_internal/_ambient_context.py +58 -0
- ansible/module_utils/_internal/_ansiballz/__init__.py +0 -0
- ansible/module_utils/_internal/_ansiballz/_extensions/__init__.py +0 -0
- ansible/module_utils/_internal/_ansiballz/_extensions/_coverage.py +45 -0
- ansible/module_utils/_internal/_ansiballz/_extensions/_pydevd.py +62 -0
- ansible/module_utils/_internal/_ansiballz/_loader.py +81 -0
- ansible/module_utils/_internal/_ansiballz/_respawn.py +32 -0
- ansible/module_utils/_internal/_ansiballz/_respawn_wrapper.py +23 -0
- ansible/module_utils/_internal/_concurrent/_daemon_threading.py +1 -0
- ansible/module_utils/_internal/_dataclass_validation.py +217 -0
- ansible/module_utils/_internal/_datatag/__init__.py +961 -0
- ansible/module_utils/_internal/_datatag/_tags.py +16 -0
- ansible/module_utils/_internal/_debugging.py +31 -0
- ansible/module_utils/_internal/_deprecator.py +157 -0
- ansible/module_utils/_internal/_errors.py +101 -0
- ansible/module_utils/_internal/_event_utils.py +61 -0
- ansible/module_utils/_internal/_json/__init__.py +63 -0
- ansible/module_utils/_internal/_json/_legacy_encoder.py +26 -0
- ansible/module_utils/_internal/_json/_profiles/__init__.py +428 -0
- ansible/module_utils/_internal/_json/_profiles/_fallback_to_str.py +73 -0
- ansible/module_utils/_internal/_json/_profiles/_module_legacy_c2m.py +33 -0
- ansible/module_utils/_internal/_json/_profiles/_module_legacy_m2c.py +37 -0
- ansible/module_utils/_internal/_json/_profiles/_module_modern_c2m.py +35 -0
- ansible/module_utils/_internal/_json/_profiles/_module_modern_m2c.py +33 -0
- ansible/module_utils/_internal/_json/_profiles/_tagless.py +52 -0
- ansible/module_utils/_internal/_messages.py +130 -0
- ansible/module_utils/_internal/_patches/__init__.py +66 -0
- ansible/module_utils/_internal/_patches/_dataclass_annotation_patch.py +53 -0
- ansible/module_utils/_internal/_patches/_socket_patch.py +34 -0
- ansible/module_utils/_internal/_patches/_sys_intern_patch.py +34 -0
- ansible/module_utils/_internal/_plugin_info.py +38 -0
- ansible/module_utils/_internal/_stack.py +22 -0
- ansible/module_utils/_internal/_testing.py +0 -0
- ansible/module_utils/_internal/_text_utils.py +6 -0
- ansible/module_utils/_internal/_traceback.py +92 -0
- ansible/module_utils/_internal/_validation.py +14 -0
- ansible/module_utils/ansible_release.py +2 -2
- ansible/module_utils/api.py +1 -2
- ansible/module_utils/basic.py +303 -202
- ansible/module_utils/common/_utils.py +24 -28
- ansible/module_utils/common/arg_spec.py +8 -3
- ansible/module_utils/common/collections.py +7 -2
- ansible/module_utils/common/dict_transformations.py +2 -2
- ansible/module_utils/common/file.py +2 -2
- ansible/module_utils/common/json.py +90 -84
- ansible/module_utils/common/locale.py +2 -2
- ansible/module_utils/common/parameters.py +27 -24
- ansible/module_utils/common/process.py +2 -3
- ansible/module_utils/common/respawn.py +11 -33
- ansible/module_utils/common/sentinel.py +66 -0
- ansible/module_utils/common/sys_info.py +8 -8
- ansible/module_utils/common/text/converters.py +16 -37
- ansible/module_utils/common/validation.py +35 -24
- ansible/module_utils/common/warnings.py +143 -25
- ansible/module_utils/common/yaml.py +29 -3
- ansible/module_utils/compat/datetime.py +33 -21
- ansible/module_utils/compat/paramiko.py +21 -10
- ansible/module_utils/compat/typing.py +6 -5
- ansible/module_utils/connection.py +10 -13
- ansible/module_utils/csharp/Ansible.Basic.cs +15 -12
- ansible/module_utils/csharp/Ansible.Become.cs +1 -0
- ansible/module_utils/csharp/Ansible.Privilege.cs +2 -2
- ansible/module_utils/csharp/Ansible._Async.cs +517 -0
- ansible/module_utils/datatag.py +49 -0
- ansible/module_utils/distro/__init__.py +2 -2
- ansible/module_utils/facts/ansible_collector.py +4 -5
- ansible/module_utils/facts/collector.py +13 -14
- ansible/module_utils/facts/compat.py +4 -4
- ansible/module_utils/facts/default_collectors.py +1 -1
- ansible/module_utils/facts/hardware/aix.py +34 -0
- ansible/module_utils/facts/hardware/base.py +2 -2
- ansible/module_utils/facts/hardware/darwin.py +1 -3
- ansible/module_utils/facts/hardware/freebsd.py +2 -2
- ansible/module_utils/facts/hardware/linux.py +5 -5
- ansible/module_utils/facts/namespace.py +1 -1
- ansible/module_utils/facts/network/base.py +1 -1
- ansible/module_utils/facts/network/fc_wwn.py +1 -2
- ansible/module_utils/facts/network/iscsi.py +1 -2
- ansible/module_utils/facts/network/nvme.py +1 -2
- ansible/module_utils/facts/other/facter.py +2 -3
- ansible/module_utils/facts/other/ohai.py +2 -3
- ansible/module_utils/facts/sysctl.py +4 -6
- ansible/module_utils/facts/system/apparmor.py +1 -2
- ansible/module_utils/facts/system/caps.py +3 -3
- ansible/module_utils/facts/system/chroot.py +1 -2
- ansible/module_utils/facts/system/cmdline.py +1 -2
- ansible/module_utils/facts/system/date_time.py +5 -3
- ansible/module_utils/facts/system/distribution.py +27 -13
- ansible/module_utils/facts/system/dns.py +1 -1
- ansible/module_utils/facts/system/env.py +1 -2
- ansible/module_utils/facts/system/fips.py +7 -20
- ansible/module_utils/facts/system/loadavg.py +1 -2
- ansible/module_utils/facts/system/local.py +2 -3
- ansible/module_utils/facts/system/lsb.py +1 -2
- ansible/module_utils/facts/system/pkg_mgr.py +1 -2
- ansible/module_utils/facts/system/platform.py +1 -2
- ansible/module_utils/facts/system/python.py +1 -2
- ansible/module_utils/facts/system/selinux.py +1 -1
- ansible/module_utils/facts/system/service_mgr.py +1 -2
- ansible/module_utils/facts/system/ssh_pub_keys.py +1 -1
- ansible/module_utils/facts/system/systemd.py +1 -1
- ansible/module_utils/facts/system/user.py +1 -2
- ansible/module_utils/facts/utils.py +3 -3
- ansible/module_utils/facts/virtual/base.py +1 -1
- ansible/module_utils/facts/virtual/linux.py +3 -3
- ansible/module_utils/facts/virtual/sunos.py +3 -15
- ansible/module_utils/facts/virtual/sysctl.py +3 -16
- ansible/module_utils/json_utils.py +2 -2
- ansible/module_utils/parsing/convert_bool.py +7 -1
- ansible/module_utils/powershell/Ansible.ModuleUtils.AddType.psm1 +1 -1
- ansible/module_utils/powershell/Ansible.ModuleUtils.CamelConversion.psm1 +1 -1
- ansible/module_utils/powershell/Ansible.ModuleUtils.CommandUtil.psm1 +1 -1
- ansible/module_utils/powershell/Ansible.ModuleUtils.WebRequest.psm1 +1 -1
- ansible/module_utils/service.py +21 -31
- ansible/module_utils/splitter.py +7 -7
- ansible/module_utils/testing.py +31 -0
- ansible/module_utils/urls.py +64 -35
- ansible/modules/add_host.py +4 -4
- ansible/modules/apt.py +69 -49
- ansible/modules/apt_key.py +19 -12
- ansible/modules/apt_repository.py +32 -51
- ansible/modules/assemble.py +16 -14
- ansible/modules/assert.py +4 -4
- ansible/modules/async_status.py +24 -24
- ansible/modules/async_wrapper.py +20 -25
- ansible/modules/blockinfile.py +6 -7
- ansible/modules/command.py +13 -20
- ansible/modules/copy.py +60 -147
- ansible/modules/cron.py +24 -21
- ansible/modules/deb822_repository.py +8 -9
- ansible/modules/debconf.py +5 -5
- ansible/modules/debug.py +4 -4
- ansible/modules/dnf.py +8 -8
- ansible/modules/dnf5.py +39 -13
- ansible/modules/dpkg_selections.py +4 -4
- ansible/modules/expect.py +13 -15
- ansible/modules/fail.py +4 -4
- ansible/modules/fetch.py +4 -4
- ansible/modules/file.py +184 -144
- ansible/modules/find.py +22 -20
- ansible/modules/gather_facts.py +3 -3
- ansible/modules/get_url.py +77 -54
- ansible/modules/getent.py +7 -9
- ansible/modules/git.py +38 -38
- ansible/modules/group.py +6 -6
- ansible/modules/group_by.py +4 -4
- ansible/modules/hostname.py +15 -32
- ansible/modules/import_playbook.py +6 -6
- ansible/modules/import_role.py +6 -6
- ansible/modules/import_tasks.py +6 -6
- ansible/modules/include_role.py +6 -6
- ansible/modules/include_tasks.py +6 -6
- ansible/modules/include_vars.py +6 -6
- ansible/modules/iptables.py +86 -73
- ansible/modules/known_hosts.py +22 -24
- ansible/modules/lineinfile.py +5 -5
- ansible/modules/meta.py +4 -4
- ansible/modules/mount_facts.py +2 -2
- ansible/modules/package.py +10 -4
- ansible/modules/package_facts.py +22 -10
- ansible/modules/pause.py +6 -6
- ansible/modules/ping.py +6 -6
- ansible/modules/pip.py +21 -26
- ansible/modules/raw.py +6 -6
- ansible/modules/reboot.py +6 -6
- ansible/modules/replace.py +10 -14
- ansible/modules/rpm_key.py +7 -8
- ansible/modules/script.py +4 -4
- ansible/modules/service.py +10 -17
- ansible/modules/service_facts.py +87 -10
- ansible/modules/set_fact.py +5 -5
- ansible/modules/set_stats.py +4 -4
- ansible/modules/setup.py +2 -2
- ansible/modules/shell.py +6 -6
- ansible/modules/slurp.py +16 -19
- ansible/modules/stat.py +15 -31
- ansible/modules/subversion.py +15 -15
- ansible/modules/systemd.py +7 -7
- ansible/modules/systemd_service.py +7 -7
- ansible/modules/sysvinit.py +9 -9
- ansible/modules/tempfile.py +5 -6
- ansible/modules/template.py +6 -6
- ansible/modules/unarchive.py +38 -17
- ansible/modules/uri.py +33 -26
- ansible/modules/user.py +45 -32
- ansible/modules/validate_argument_spec.py +10 -7
- ansible/modules/wait_for.py +70 -60
- ansible/modules/wait_for_connection.py +6 -6
- ansible/modules/yum_repository.py +10 -9
- ansible/parsing/ajson.py +17 -37
- ansible/parsing/dataloader.py +99 -54
- ansible/parsing/mod_args.py +62 -60
- ansible/parsing/plugin_docs.py +21 -86
- ansible/parsing/quoting.py +1 -1
- ansible/parsing/splitter.py +27 -12
- ansible/parsing/utils/addresses.py +24 -24
- ansible/parsing/utils/jsonify.py +5 -1
- ansible/parsing/utils/yaml.py +32 -61
- ansible/parsing/vault/__init__.py +327 -99
- ansible/parsing/yaml/__init__.py +0 -18
- ansible/parsing/yaml/dumper.py +6 -120
- ansible/parsing/yaml/loader.py +6 -39
- ansible/parsing/yaml/objects.py +43 -335
- ansible/playbook/__init__.py +1 -1
- ansible/playbook/attribute.py +8 -3
- ansible/playbook/base.py +187 -134
- ansible/playbook/block.py +26 -24
- ansible/playbook/collectionsearch.py +1 -15
- ansible/playbook/conditional.py +3 -77
- ansible/playbook/handler.py +8 -2
- ansible/playbook/helpers.py +41 -53
- ansible/playbook/included_file.py +32 -26
- ansible/playbook/loop_control.py +2 -2
- ansible/playbook/play.py +85 -44
- ansible/playbook/play_context.py +14 -17
- ansible/playbook/playbook_include.py +27 -62
- ansible/playbook/role/__init__.py +64 -49
- ansible/playbook/role/definition.py +15 -17
- ansible/playbook/role/include.py +2 -4
- ansible/playbook/role/metadata.py +10 -11
- ansible/playbook/role_include.py +3 -3
- ansible/playbook/taggable.py +28 -12
- ansible/playbook/task.py +192 -121
- ansible/playbook/task_include.py +5 -5
- ansible/plugins/__init__.py +58 -26
- ansible/plugins/action/__init__.py +188 -186
- ansible/plugins/action/add_host.py +2 -2
- ansible/plugins/action/assemble.py +11 -18
- ansible/plugins/action/assert.py +55 -67
- ansible/plugins/action/async_status.py +7 -2
- ansible/plugins/action/copy.py +14 -17
- ansible/plugins/action/debug.py +37 -31
- ansible/plugins/action/dnf.py +3 -4
- ansible/plugins/action/fail.py +1 -1
- ansible/plugins/action/fetch.py +7 -8
- ansible/plugins/action/gather_facts.py +13 -14
- ansible/plugins/action/group_by.py +1 -1
- ansible/plugins/action/include_vars.py +10 -11
- ansible/plugins/action/package.py +8 -14
- ansible/plugins/action/pause.py +2 -2
- ansible/plugins/action/script.py +27 -38
- ansible/plugins/action/service.py +9 -18
- ansible/plugins/action/set_fact.py +3 -12
- ansible/plugins/action/set_stats.py +3 -8
- ansible/plugins/action/template.py +47 -67
- ansible/plugins/action/unarchive.py +6 -16
- ansible/plugins/action/uri.py +9 -20
- ansible/plugins/action/validate_argument_spec.py +5 -5
- ansible/plugins/action/wait_for_connection.py +1 -1
- ansible/plugins/become/__init__.py +31 -8
- ansible/plugins/become/runas.py +71 -0
- ansible/plugins/become/su.py +13 -8
- ansible/plugins/become/sudo.py +19 -0
- ansible/plugins/cache/__init__.py +52 -63
- ansible/plugins/cache/base.py +8 -0
- ansible/plugins/cache/jsonfile.py +10 -16
- ansible/plugins/cache/memory.py +6 -12
- ansible/plugins/callback/__init__.py +294 -201
- ansible/plugins/callback/default.py +99 -95
- ansible/plugins/callback/junit.py +44 -43
- ansible/plugins/callback/minimal.py +28 -25
- ansible/plugins/callback/oneline.py +34 -21
- ansible/plugins/callback/tree.py +27 -16
- ansible/plugins/connection/__init__.py +47 -34
- ansible/plugins/connection/local.py +156 -60
- ansible/plugins/connection/paramiko_ssh.py +34 -24
- ansible/plugins/connection/psrp.py +76 -165
- ansible/plugins/connection/ssh.py +326 -86
- ansible/plugins/connection/winrm.py +62 -141
- ansible/plugins/doc_fragments/action_common_attributes.py +14 -14
- ansible/plugins/doc_fragments/action_core.py +6 -6
- ansible/plugins/doc_fragments/backup.py +2 -2
- ansible/plugins/doc_fragments/checksum_common.py +27 -0
- ansible/plugins/doc_fragments/constructed.py +8 -4
- ansible/plugins/doc_fragments/decrypt.py +2 -2
- ansible/plugins/doc_fragments/default_callback.py +2 -2
- ansible/plugins/doc_fragments/files.py +2 -2
- ansible/plugins/doc_fragments/inventory_cache.py +2 -2
- ansible/plugins/doc_fragments/result_format_callback.py +2 -2
- ansible/plugins/doc_fragments/return_common.py +2 -2
- ansible/plugins/doc_fragments/template_common.py +4 -4
- ansible/plugins/doc_fragments/url.py +17 -1
- ansible/plugins/doc_fragments/url_windows.py +2 -2
- ansible/plugins/doc_fragments/validate.py +2 -2
- ansible/plugins/doc_fragments/vars_plugin_staging.py +2 -2
- ansible/plugins/filter/__init__.py +6 -2
- ansible/plugins/filter/b64decode.yml +22 -0
- ansible/plugins/filter/b64encode.yml +22 -0
- ansible/plugins/filter/bool.yml +11 -4
- ansible/plugins/filter/core.py +245 -120
- ansible/plugins/filter/encryption.py +42 -34
- ansible/plugins/filter/flatten.yml +3 -2
- ansible/plugins/filter/human_to_bytes.yml +1 -1
- ansible/plugins/filter/mathstuff.py +30 -37
- ansible/plugins/filter/password_hash.yml +8 -0
- ansible/plugins/filter/pow.yml +1 -1
- ansible/plugins/filter/regex_search.yml +1 -4
- ansible/plugins/filter/root.yml +1 -1
- ansible/plugins/filter/split.yml +1 -1
- ansible/plugins/filter/strftime.yml +3 -3
- ansible/plugins/filter/to_nice_yaml.yml +0 -4
- ansible/plugins/filter/to_uuid.yml +1 -1
- ansible/plugins/filter/to_yaml.yml +0 -4
- ansible/plugins/filter/unvault.yml +1 -1
- ansible/plugins/filter/urls.py +1 -1
- ansible/plugins/filter/urlsplit.py +8 -9
- ansible/plugins/filter/vault.yml +14 -9
- ansible/plugins/filter/win_basename.yml +6 -1
- ansible/plugins/filter/win_dirname.yml +5 -0
- ansible/plugins/inventory/__init__.py +107 -86
- ansible/plugins/inventory/advanced_host_list.py +7 -5
- ansible/plugins/inventory/auto.py +11 -4
- ansible/plugins/inventory/constructed.py +21 -24
- ansible/plugins/inventory/generator.py +16 -11
- ansible/plugins/inventory/host_list.py +7 -5
- ansible/plugins/inventory/ini.py +78 -44
- ansible/plugins/inventory/script.py +190 -120
- ansible/plugins/inventory/toml.py +16 -126
- ansible/plugins/inventory/yaml.py +10 -8
- ansible/plugins/list.py +72 -19
- ansible/plugins/loader.py +383 -198
- ansible/plugins/lookup/__init__.py +21 -4
- ansible/plugins/lookup/config.py +21 -35
- ansible/plugins/lookup/csvfile.py +19 -73
- ansible/plugins/lookup/dict.py +1 -6
- ansible/plugins/lookup/env.py +12 -9
- ansible/plugins/lookup/file.py +5 -8
- ansible/plugins/lookup/first_found.py +87 -55
- ansible/plugins/lookup/indexed_items.py +1 -10
- ansible/plugins/lookup/ini.py +14 -13
- ansible/plugins/lookup/items.py +1 -1
- ansible/plugins/lookup/lines.py +8 -1
- ansible/plugins/lookup/list.py +1 -1
- ansible/plugins/lookup/nested.py +2 -18
- ansible/plugins/lookup/password.py +5 -5
- ansible/plugins/lookup/pipe.py +5 -7
- ansible/plugins/lookup/sequence.py +18 -8
- ansible/plugins/lookup/subelements.py +1 -4
- ansible/plugins/lookup/template.py +47 -36
- ansible/plugins/lookup/together.py +0 -12
- ansible/plugins/lookup/unvault.py +1 -5
- ansible/plugins/lookup/url.py +4 -10
- ansible/plugins/lookup/vars.py +16 -24
- ansible/plugins/shell/__init__.py +58 -4
- ansible/plugins/shell/cmd.py +2 -2
- ansible/plugins/shell/powershell.py +106 -31
- ansible/plugins/shell/sh.py +13 -7
- ansible/plugins/strategy/__init__.py +168 -193
- ansible/plugins/strategy/debug.py +2 -2
- ansible/plugins/strategy/free.py +16 -31
- ansible/plugins/strategy/host_pinned.py +2 -2
- ansible/plugins/strategy/linear.py +41 -41
- ansible/plugins/terminal/__init__.py +4 -4
- ansible/plugins/test/__init__.py +7 -2
- ansible/plugins/test/core.py +75 -35
- ansible/plugins/test/files.py +1 -1
- ansible/plugins/test/finished.yml +1 -1
- ansible/plugins/test/mathstuff.py +3 -3
- ansible/plugins/test/uri.py +5 -8
- ansible/plugins/vars/host_group_vars.py +7 -14
- ansible/release.py +2 -2
- ansible/template/__init__.py +353 -943
- ansible/utils/__init__.py +0 -18
- ansible/utils/collection_loader/__init__.py +54 -5
- ansible/utils/collection_loader/_collection_config.py +5 -6
- ansible/utils/collection_loader/_collection_finder.py +82 -96
- ansible/utils/collection_loader/_collection_meta.py +15 -8
- ansible/utils/display.py +485 -73
- ansible/utils/encrypt.py +27 -19
- ansible/utils/fqcn.py +2 -2
- ansible/utils/galaxy.py +2 -2
- ansible/utils/hashing.py +8 -10
- ansible/utils/helpers.py +2 -2
- ansible/utils/listify.py +10 -8
- ansible/utils/lock.py +2 -2
- ansible/utils/path.py +10 -12
- ansible/utils/plugin_docs.py +16 -14
- ansible/utils/py3compat.py +2 -7
- ansible/utils/sentinel.py +4 -62
- ansible/utils/singleton.py +2 -0
- ansible/utils/ssh_functions.py +6 -2
- ansible/utils/unsafe_proxy.py +23 -332
- ansible/utils/vars.py +55 -8
- ansible/utils/version.py +2 -2
- ansible/vars/clean.py +5 -5
- ansible/vars/hostvars.py +60 -90
- ansible/vars/manager.py +220 -285
- ansible/vars/plugins.py +4 -4
- ansible/vars/reserved.py +13 -12
- {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/METADATA +4 -3
- ansible_core-2.19.0.dist-info/RECORD +1097 -0
- ansible_core-2.19.0.dist-info/licenses/licenses/BSD-3-Clause.txt +28 -0
- ansible_test/_data/completion/docker.txt +7 -7
- ansible_test/_data/completion/remote.txt +6 -6
- ansible_test/_data/completion/windows.txt +1 -0
- ansible_test/_data/requirements/ansible.txt +2 -2
- ansible_test/_data/requirements/sanity.ansible-doc.txt +3 -3
- ansible_test/_data/requirements/sanity.changelog.txt +2 -2
- ansible_test/_data/requirements/sanity.import.plugin.txt +2 -2
- ansible_test/_data/requirements/sanity.pep8.txt +1 -1
- ansible_test/_data/requirements/sanity.pylint.txt +5 -5
- ansible_test/_data/requirements/sanity.validate-modules.txt +2 -2
- ansible_test/_data/requirements/sanity.yamllint.txt +1 -1
- ansible_test/_data/requirements/units.txt +1 -0
- ansible_test/_internal/__init__.py +6 -0
- ansible_test/_internal/ansible_util.py +3 -1
- ansible_test/_internal/become.py +1 -0
- ansible_test/_internal/bootstrap.py +1 -0
- ansible_test/_internal/cache.py +1 -0
- ansible_test/_internal/cgroup.py +1 -0
- ansible_test/_internal/ci/__init__.py +1 -0
- ansible_test/_internal/ci/azp.py +1 -0
- ansible_test/_internal/ci/local.py +1 -0
- ansible_test/_internal/classification/__init__.py +1 -0
- ansible_test/_internal/classification/common.py +1 -0
- ansible_test/_internal/classification/csharp.py +1 -0
- ansible_test/_internal/classification/powershell.py +1 -0
- ansible_test/_internal/classification/python.py +1 -0
- ansible_test/_internal/cli/__init__.py +1 -0
- ansible_test/_internal/cli/actions.py +1 -0
- ansible_test/_internal/cli/argparsing/__init__.py +1 -0
- ansible_test/_internal/cli/argparsing/actions.py +1 -0
- ansible_test/_internal/cli/argparsing/argcompletion.py +1 -0
- ansible_test/_internal/cli/argparsing/parsers.py +1 -0
- ansible_test/_internal/cli/commands/__init__.py +11 -5
- ansible_test/_internal/cli/commands/coverage/__init__.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/__init__.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/__init__.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/combine.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/expand.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/filter.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/generate.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/missing.py +1 -0
- ansible_test/_internal/cli/commands/coverage/combine.py +1 -0
- ansible_test/_internal/cli/commands/coverage/erase.py +1 -0
- ansible_test/_internal/cli/commands/coverage/html.py +1 -0
- ansible_test/_internal/cli/commands/coverage/report.py +1 -0
- ansible_test/_internal/cli/commands/coverage/xml.py +1 -0
- ansible_test/_internal/cli/commands/env.py +1 -0
- ansible_test/_internal/cli/commands/integration/__init__.py +1 -0
- ansible_test/_internal/cli/commands/integration/network.py +1 -0
- ansible_test/_internal/cli/commands/integration/posix.py +1 -0
- ansible_test/_internal/cli/commands/integration/windows.py +1 -0
- ansible_test/_internal/cli/commands/sanity.py +9 -0
- ansible_test/_internal/cli/commands/shell.py +1 -0
- ansible_test/_internal/cli/commands/units.py +1 -0
- ansible_test/_internal/cli/compat.py +1 -0
- ansible_test/_internal/cli/completers.py +1 -0
- ansible_test/_internal/cli/converters.py +1 -0
- ansible_test/_internal/cli/environments.py +52 -5
- ansible_test/_internal/cli/epilog.py +1 -0
- ansible_test/_internal/cli/parsers/__init__.py +1 -0
- ansible_test/_internal/cli/parsers/base_argument_parsers.py +1 -0
- ansible_test/_internal/cli/parsers/helpers.py +1 -0
- ansible_test/_internal/cli/parsers/host_config_parsers.py +1 -0
- ansible_test/_internal/cli/parsers/key_value_parsers.py +1 -0
- ansible_test/_internal/cli/parsers/value_parsers.py +1 -0
- ansible_test/_internal/commands/__init__.py +1 -0
- ansible_test/_internal/commands/coverage/__init__.py +3 -2
- ansible_test/_internal/commands/coverage/analyze/__init__.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/__init__.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/combine.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/expand.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/filter.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/generate.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/missing.py +1 -0
- ansible_test/_internal/commands/coverage/combine.py +2 -1
- ansible_test/_internal/commands/coverage/erase.py +1 -0
- ansible_test/_internal/commands/coverage/html.py +1 -0
- ansible_test/_internal/commands/coverage/report.py +1 -0
- ansible_test/_internal/commands/coverage/xml.py +1 -0
- ansible_test/_internal/commands/env/__init__.py +2 -0
- ansible_test/_internal/commands/integration/__init__.py +22 -5
- ansible_test/_internal/commands/integration/cloud/__init__.py +1 -0
- ansible_test/_internal/commands/integration/cloud/acme.py +2 -1
- ansible_test/_internal/commands/integration/cloud/aws.py +1 -0
- ansible_test/_internal/commands/integration/cloud/azure.py +1 -0
- ansible_test/_internal/commands/integration/cloud/cs.py +1 -0
- ansible_test/_internal/commands/integration/cloud/digitalocean.py +1 -0
- ansible_test/_internal/commands/integration/cloud/galaxy.py +3 -2
- ansible_test/_internal/commands/integration/cloud/hcloud.py +1 -0
- ansible_test/_internal/commands/integration/cloud/httptester.py +3 -2
- ansible_test/_internal/commands/integration/cloud/nios.py +2 -1
- ansible_test/_internal/commands/integration/cloud/opennebula.py +1 -0
- ansible_test/_internal/commands/integration/cloud/openshift.py +1 -0
- ansible_test/_internal/commands/integration/cloud/scaleway.py +1 -0
- ansible_test/_internal/commands/integration/cloud/vcenter.py +1 -0
- ansible_test/_internal/commands/integration/cloud/vultr.py +1 -0
- ansible_test/_internal/commands/integration/coverage.py +8 -2
- ansible_test/_internal/commands/integration/filters.py +1 -0
- ansible_test/_internal/commands/integration/network.py +1 -0
- ansible_test/_internal/commands/integration/posix.py +1 -0
- ansible_test/_internal/commands/integration/windows.py +1 -0
- ansible_test/_internal/commands/sanity/__init__.py +19 -2
- ansible_test/_internal/commands/sanity/ansible_doc.py +1 -0
- ansible_test/_internal/commands/sanity/bin_symlinks.py +1 -0
- ansible_test/_internal/commands/sanity/compile.py +1 -0
- ansible_test/_internal/commands/sanity/ignores.py +1 -0
- ansible_test/_internal/commands/sanity/import.py +1 -0
- ansible_test/_internal/commands/sanity/integration_aliases.py +12 -0
- ansible_test/_internal/commands/sanity/pep8.py +1 -0
- ansible_test/_internal/commands/sanity/pslint.py +1 -0
- ansible_test/_internal/commands/sanity/pylint.py +25 -26
- ansible_test/_internal/commands/sanity/shellcheck.py +1 -0
- ansible_test/_internal/commands/sanity/validate_modules.py +1 -0
- ansible_test/_internal/commands/sanity/yamllint.py +1 -0
- ansible_test/_internal/commands/shell/__init__.py +44 -4
- ansible_test/_internal/commands/units/__init__.py +5 -1
- ansible_test/_internal/compat/__init__.py +1 -0
- ansible_test/_internal/compat/packaging.py +1 -0
- ansible_test/_internal/compat/yaml.py +1 -0
- ansible_test/_internal/completion.py +1 -0
- ansible_test/_internal/config.py +23 -13
- ansible_test/_internal/connections.py +1 -0
- ansible_test/_internal/constants.py +1 -0
- ansible_test/_internal/containers.py +1 -0
- ansible_test/_internal/content_config.py +1 -0
- ansible_test/_internal/core_ci.py +1 -0
- ansible_test/_internal/coverage_util.py +11 -10
- ansible_test/_internal/data.py +1 -0
- ansible_test/_internal/debugging.py +166 -0
- ansible_test/_internal/delegation.py +22 -13
- ansible_test/_internal/dev/__init__.py +1 -0
- ansible_test/_internal/dev/container_probe.py +1 -0
- ansible_test/_internal/diff.py +3 -2
- ansible_test/_internal/docker_util.py +2 -1
- ansible_test/_internal/encoding.py +1 -0
- ansible_test/_internal/executor.py +1 -0
- ansible_test/_internal/git.py +1 -0
- ansible_test/_internal/host_configs.py +1 -0
- ansible_test/_internal/host_profiles.py +260 -16
- ansible_test/_internal/http.py +1 -0
- ansible_test/_internal/init.py +1 -0
- ansible_test/_internal/inventory.py +39 -3
- ansible_test/_internal/io.py +1 -0
- ansible_test/_internal/metadata.py +95 -4
- ansible_test/_internal/payload.py +1 -0
- ansible_test/_internal/processes.py +80 -0
- ansible_test/_internal/provider/__init__.py +1 -0
- ansible_test/_internal/provider/layout/__init__.py +1 -0
- ansible_test/_internal/provider/layout/ansible.py +1 -0
- ansible_test/_internal/provider/layout/collection.py +1 -0
- ansible_test/_internal/provider/layout/unsupported.py +1 -0
- ansible_test/_internal/provider/source/__init__.py +1 -0
- ansible_test/_internal/provider/source/git.py +1 -0
- ansible_test/_internal/provider/source/installed.py +1 -0
- ansible_test/_internal/provider/source/unsupported.py +1 -0
- ansible_test/_internal/provider/source/unversioned.py +1 -0
- ansible_test/_internal/provisioning.py +11 -4
- ansible_test/_internal/pypi_proxy.py +6 -5
- ansible_test/_internal/python_requirements.py +28 -0
- ansible_test/_internal/ssh.py +2 -5
- ansible_test/_internal/target.py +9 -0
- ansible_test/_internal/test.py +3 -2
- ansible_test/_internal/thread.py +3 -1
- ansible_test/_internal/timeout.py +2 -1
- ansible_test/_internal/util.py +41 -12
- ansible_test/_internal/util_common.py +18 -5
- ansible_test/_internal/venv.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/action-plugin-docs.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/changelog/sphinx.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/changelog.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/empty-init.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/line-endings.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-assert.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-get-exception.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-illegal-filenames.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-smart-quotes.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/replace-urlopen.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/runtime-metadata.py +28 -1
- ansible_test/_util/controller/sanity/code-smell/shebang.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/symlinks.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/use-argspec-type-path.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/use-compat-six.py +1 -0
- ansible_test/_util/controller/sanity/integration-aliases/yaml_to_json.py +2 -1
- ansible_test/_util/controller/sanity/pep8/current-ignore.txt +4 -0
- ansible_test/_util/controller/sanity/pylint/config/ansible-test-target.cfg +8 -5
- ansible_test/_util/controller/sanity/pylint/config/ansible-test.cfg +8 -5
- ansible_test/_util/controller/sanity/pylint/config/code-smell.cfg +8 -5
- ansible_test/_util/controller/sanity/pylint/config/collection.cfg +4 -5
- ansible_test/_util/controller/sanity/pylint/config/default.cfg +8 -7
- ansible_test/_util/controller/sanity/pylint/plugins/deprecated_calls.py +541 -0
- ansible_test/_util/controller/sanity/pylint/plugins/deprecated_comment.py +137 -0
- ansible_test/_util/controller/sanity/pylint/plugins/hide_unraisable.py +1 -0
- ansible_test/_util/controller/sanity/pylint/plugins/string_format.py +1 -8
- ansible_test/_util/controller/sanity/pylint/plugins/unwanted.py +1 -8
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py +55 -28
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/module_args.py +12 -5
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/schema.py +13 -2
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/utils.py +1 -0
- ansible_test/_util/controller/sanity/yamllint/yamllinter.py +35 -17
- ansible_test/_util/controller/tools/collection_detail.py +1 -0
- ansible_test/_util/controller/tools/yaml_to_json.py +2 -1
- ansible_test/_util/target/injector/python.py +8 -0
- ansible_test/_util/target/pytest/plugins/ansible_forked.py +6 -1
- ansible_test/_util/target/pytest/plugins/ansible_pytest_collections.py +2 -1
- ansible_test/_util/target/pytest/plugins/ansible_pytest_coverage.py +1 -0
- ansible_test/_util/target/sanity/compile/compile.py +1 -0
- ansible_test/_util/target/sanity/import/importer.py +15 -16
- ansible_test/_util/target/setup/bootstrap.sh +9 -20
- ansible_test/_util/target/setup/probe_cgroups.py +1 -0
- ansible_test/_util/target/setup/quiet_pip.py +1 -0
- ansible_test/_util/target/setup/requirements.py +38 -36
- ansible_test/_util/target/tools/virtualenvcheck.py +2 -1
- ansible_test/_util/target/tools/yamlcheck.py +2 -1
- ansible/compat/selectors.py +0 -32
- ansible/errors/yaml_strings.py +0 -138
- ansible/executor/action_write_locks.py +0 -44
- ansible/executor/discovery/python_target.py +0 -47
- ansible/executor/powershell/module_powershell_wrapper.ps1 +0 -86
- ansible/executor/powershell/module_script_wrapper.ps1 +0 -22
- ansible/module_utils/compat/importlib.py +0 -26
- ansible/module_utils/compat/selectors.py +0 -32
- ansible/module_utils/pycompat24.py +0 -73
- ansible/parsing/yaml/constructor.py +0 -178
- ansible/template/native_helpers.py +0 -251
- ansible/template/template.py +0 -43
- ansible/template/vars.py +0 -77
- ansible/utils/native_jinja.py +0 -11
- ansible/vars/fact_cache.py +0 -71
- ansible_core-2.18.7rc1.dist-info/RECORD +0 -992
- ansible_test/_util/controller/sanity/pylint/plugins/deprecated.py +0 -411
- {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/WHEEL +0 -0
- {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/entry_points.txt +0 -0
- {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/COPYING +0 -0
- {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/Apache-License.txt +0 -0
- {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/MIT-license.txt +0 -0
- {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/PSF-license.txt +0 -0
- {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/simplified_bsd.txt +0 -0
- {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/top_level.txt +0 -0
|
@@ -10,13 +10,13 @@ from ansible.utils.vars import combine_vars
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class ActionModule(ActionBase):
|
|
13
|
-
|
|
13
|
+
""" Validate an arg spec"""
|
|
14
14
|
|
|
15
15
|
TRANSFERS_FILES = False
|
|
16
16
|
_requires_connection = False
|
|
17
17
|
|
|
18
18
|
def get_args_from_task_vars(self, argument_spec, task_vars):
|
|
19
|
-
|
|
19
|
+
"""
|
|
20
20
|
Get any arguments that may come from `task_vars`.
|
|
21
21
|
|
|
22
22
|
Expand templated variables so we can validate the actual values.
|
|
@@ -25,7 +25,7 @@ class ActionModule(ActionBase):
|
|
|
25
25
|
:param task_vars: A dict of task variables.
|
|
26
26
|
|
|
27
27
|
:returns: A dict of values that can be validated against the arg spec.
|
|
28
|
-
|
|
28
|
+
"""
|
|
29
29
|
args = {}
|
|
30
30
|
|
|
31
31
|
for argument_name, argument_attrs in argument_spec.items():
|
|
@@ -35,7 +35,7 @@ class ActionModule(ActionBase):
|
|
|
35
35
|
return args
|
|
36
36
|
|
|
37
37
|
def run(self, tmp=None, task_vars=None):
|
|
38
|
-
|
|
38
|
+
"""
|
|
39
39
|
Validate an argument specification against a provided set of data.
|
|
40
40
|
|
|
41
41
|
The `validate_argument_spec` module expects to receive the arguments:
|
|
@@ -48,7 +48,7 @@ class ActionModule(ActionBase):
|
|
|
48
48
|
:param task_vars: A dict of task variables.
|
|
49
49
|
:return: An action result dict, including a 'argument_errors' key with a
|
|
50
50
|
list of validation errors found.
|
|
51
|
-
|
|
51
|
+
"""
|
|
52
52
|
if task_vars is None:
|
|
53
53
|
task_vars = dict()
|
|
54
54
|
|
|
@@ -76,7 +76,7 @@ class ActionModule(ActionBase):
|
|
|
76
76
|
del tmp # tmp no longer has any effect
|
|
77
77
|
|
|
78
78
|
def ping_module_test(connect_timeout):
|
|
79
|
-
|
|
79
|
+
""" Test ping module, if available """
|
|
80
80
|
display.vvv("wait_for_connection: attempting ping module test")
|
|
81
81
|
# re-run interpreter discovery if we ran it in the first iteration
|
|
82
82
|
if self._discovered_interpreter_key:
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
4
4
|
from __future__ import annotations
|
|
5
5
|
|
|
6
|
+
import re
|
|
6
7
|
import shlex
|
|
7
8
|
|
|
8
9
|
from abc import abstractmethod
|
|
@@ -13,10 +14,11 @@ from gettext import dgettext
|
|
|
13
14
|
from ansible.errors import AnsibleError
|
|
14
15
|
from ansible.module_utils.common.text.converters import to_bytes
|
|
15
16
|
from ansible.plugins import AnsiblePlugin
|
|
17
|
+
from ansible.utils import display as _display
|
|
16
18
|
|
|
17
19
|
|
|
18
20
|
def _gen_id(length=32):
|
|
19
|
-
|
|
21
|
+
""" return random string used to identify the current privilege escalation """
|
|
20
22
|
return ''.join(choice(ascii_lowercase) for x in range(length))
|
|
21
23
|
|
|
22
24
|
|
|
@@ -32,6 +34,9 @@ class BecomeBase(AnsiblePlugin):
|
|
|
32
34
|
# plugin requires a tty, i.e su
|
|
33
35
|
require_tty = False
|
|
34
36
|
|
|
37
|
+
# plugin allows for pipelining execution
|
|
38
|
+
pipelining = True
|
|
39
|
+
|
|
35
40
|
# prompt to match
|
|
36
41
|
prompt = ''
|
|
37
42
|
|
|
@@ -53,11 +58,11 @@ class BecomeBase(AnsiblePlugin):
|
|
|
53
58
|
|
|
54
59
|
return getattr(playcontext, option, None)
|
|
55
60
|
|
|
56
|
-
def expect_prompt(self):
|
|
61
|
+
def expect_prompt(self) -> bool:
|
|
57
62
|
"""This function assists connection plugins in determining if they need to wait for
|
|
58
63
|
a prompt. Both a prompt and a password are required.
|
|
59
64
|
"""
|
|
60
|
-
return self.prompt and self.get_option('become_pass')
|
|
65
|
+
return bool(self.prompt and self.get_option('become_pass'))
|
|
61
66
|
|
|
62
67
|
def _build_success_command(self, cmd, shell, noexe=False):
|
|
63
68
|
if not all((cmd, shell, self.success)):
|
|
@@ -65,9 +70,8 @@ class BecomeBase(AnsiblePlugin):
|
|
|
65
70
|
|
|
66
71
|
try:
|
|
67
72
|
cmd = shlex.quote('%s %s %s %s' % (shell.ECHO, self.success, shell.COMMAND_SEP, cmd))
|
|
68
|
-
except AttributeError:
|
|
69
|
-
|
|
70
|
-
raise AnsibleError('The %s shell family is incompatible with the %s become plugin' % (shell.SHELL_FAMILY, self.name))
|
|
73
|
+
except AttributeError as ex:
|
|
74
|
+
raise AnsibleError(f'The {shell._load_name!r} shell plugin does not support become. It is missing the {ex.name!r} attribute.')
|
|
71
75
|
exe = getattr(shell, 'executable', None)
|
|
72
76
|
if exe and not noexe:
|
|
73
77
|
cmd = '%s -c %s' % (exe, cmd)
|
|
@@ -78,19 +82,38 @@ class BecomeBase(AnsiblePlugin):
|
|
|
78
82
|
self._id = _gen_id()
|
|
79
83
|
self.success = 'BECOME-SUCCESS-%s' % self._id
|
|
80
84
|
|
|
85
|
+
def strip_become_prompt(self, data: bytes) -> bytes:
|
|
86
|
+
"""
|
|
87
|
+
Strips the first found configured become prompt from `data`, trailing whitespace and anything that precedes the prompt, then returns the result.
|
|
88
|
+
If no prompt is expected, or the prompt is not `str` or `bytes`, `data` will be returned as-is.
|
|
89
|
+
"""
|
|
90
|
+
if not self.prompt or not isinstance(self.prompt, (str, bytes)) or not self.expect_prompt():
|
|
91
|
+
return data
|
|
92
|
+
|
|
93
|
+
return self._strip_through_prefix(self.prompt, data)
|
|
94
|
+
|
|
95
|
+
def strip_become_success(self, data: bytes) -> bytes:
|
|
96
|
+
"""Strips the first found success marker from `data`, trailing whitespace and anything that precedes the success marker, then returns the result."""
|
|
97
|
+
return self._strip_through_prefix(self.success, data)
|
|
98
|
+
|
|
99
|
+
@staticmethod
|
|
100
|
+
def _strip_through_prefix(match: str | bytes, data: bytes) -> bytes:
|
|
101
|
+
"""Strips the first occurrence of `match` from `data`, trailing whitespace and anything that precedes `match`, then returns the result."""
|
|
102
|
+
return re.sub(br'^.*?' + re.escape(to_bytes(match)) + br'\s*', b'', data, count=1, flags=re.DOTALL)
|
|
103
|
+
|
|
81
104
|
def check_success(self, b_output):
|
|
82
105
|
b_success = to_bytes(self.success)
|
|
83
106
|
return any(b_success in l.rstrip() for l in b_output.splitlines(True))
|
|
84
107
|
|
|
85
108
|
def check_password_prompt(self, b_output):
|
|
86
|
-
|
|
109
|
+
""" checks if the expected password prompt exists in b_output """
|
|
87
110
|
if self.prompt:
|
|
88
111
|
b_prompt = to_bytes(self.prompt).strip()
|
|
89
112
|
return any(l.strip().startswith(b_prompt) for l in b_output.splitlines())
|
|
90
113
|
return False
|
|
91
114
|
|
|
92
115
|
def _check_password_error(self, b_out, msg):
|
|
93
|
-
|
|
116
|
+
""" returns True/False if domain specific i18n version of msg is found in b_out """
|
|
94
117
|
b_fail = to_bytes(dgettext(self.name, msg))
|
|
95
118
|
return b_fail and b_fail in b_out
|
|
96
119
|
|
ansible/plugins/become/runas.py
CHANGED
|
@@ -61,6 +61,8 @@ DOCUMENTATION = """
|
|
|
61
61
|
- The Secondary Logon service (seclogon) must be running to use runas
|
|
62
62
|
"""
|
|
63
63
|
|
|
64
|
+
from ansible.errors import AnsibleError
|
|
65
|
+
from ansible.parsing.splitter import split_args
|
|
64
66
|
from ansible.plugins.become import BecomeBase
|
|
65
67
|
|
|
66
68
|
|
|
@@ -72,3 +74,72 @@ class BecomeModule(BecomeBase):
|
|
|
72
74
|
# this is a noop, the 'real' runas is implemented
|
|
73
75
|
# inside the windows powershell execution subsystem
|
|
74
76
|
return cmd
|
|
77
|
+
|
|
78
|
+
def _build_powershell_wrapper_action(self) -> tuple[str, dict[str, object], dict[str, object]]:
|
|
79
|
+
# See ansible.executor.powershell.become_wrapper.ps1 for the
|
|
80
|
+
# parameter names
|
|
81
|
+
params = {
|
|
82
|
+
'BecomeUser': self.get_option('become_user'),
|
|
83
|
+
}
|
|
84
|
+
secure_params = {}
|
|
85
|
+
|
|
86
|
+
password = self.get_option('become_pass')
|
|
87
|
+
if password:
|
|
88
|
+
secure_params['BecomePassword'] = password
|
|
89
|
+
|
|
90
|
+
flags = self.get_option('become_flags')
|
|
91
|
+
if flags:
|
|
92
|
+
split_flags = split_args(flags)
|
|
93
|
+
for flag in split_flags:
|
|
94
|
+
if '=' not in flag:
|
|
95
|
+
raise ValueError(f"become_flags entry '{flag}' is in an invalid format, must be a key=value pair")
|
|
96
|
+
|
|
97
|
+
k, v = flag.split('=', 1)
|
|
98
|
+
|
|
99
|
+
param_name, param_value = self._parse_flag(k, v)
|
|
100
|
+
params[param_name] = param_value
|
|
101
|
+
|
|
102
|
+
return 'become_wrapper.ps1', params, secure_params
|
|
103
|
+
|
|
104
|
+
def _parse_flag(self, name: str, value: str) -> tuple[str, str]:
|
|
105
|
+
logon_types = {
|
|
106
|
+
'interactive': 'Interactive',
|
|
107
|
+
'network': 'Network',
|
|
108
|
+
'batch': 'Batch',
|
|
109
|
+
'service': 'Service',
|
|
110
|
+
'unlock': 'Unlock',
|
|
111
|
+
'network_cleartext': 'NetworkCleartext',
|
|
112
|
+
'new_credentials': 'NewCredentials',
|
|
113
|
+
}
|
|
114
|
+
logon_flags = {
|
|
115
|
+
'none': 'None',
|
|
116
|
+
'with_profile': 'WithProfile',
|
|
117
|
+
'netcredentials_only': 'NetCredentialsOnly',
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
match name.lower():
|
|
121
|
+
case 'logon_type':
|
|
122
|
+
param_name = 'LogonType'
|
|
123
|
+
if param_value := logon_types.get(value.lower(), None):
|
|
124
|
+
return param_name, param_value
|
|
125
|
+
else:
|
|
126
|
+
raise AnsibleError(f"become_flags logon_type value '{value}' is not valid, valid values are: {', '.join(logon_types.keys())}")
|
|
127
|
+
|
|
128
|
+
case 'logon_flags':
|
|
129
|
+
param_name = 'LogonFlags'
|
|
130
|
+
flags = value.split(',')
|
|
131
|
+
|
|
132
|
+
param_values: list[str] = []
|
|
133
|
+
for flag in flags:
|
|
134
|
+
if not flag:
|
|
135
|
+
continue
|
|
136
|
+
|
|
137
|
+
if flag_value := logon_flags.get(flag.lower(), None):
|
|
138
|
+
param_values.append(flag_value)
|
|
139
|
+
else:
|
|
140
|
+
raise AnsibleError(f"become_flags logon_flags value '{flag}' is not valid, valid values are: {', '.join(logon_flags.keys())}")
|
|
141
|
+
|
|
142
|
+
return param_name, ", ".join(param_values)
|
|
143
|
+
|
|
144
|
+
case _:
|
|
145
|
+
raise AnsibleError(f"become_flags key '{name}' is not a valid runas flag, must be 'logon_type' or 'logon_flags'")
|
ansible/plugins/become/su.py
CHANGED
|
@@ -93,7 +93,7 @@ DOCUMENTATION = """
|
|
|
93
93
|
import re
|
|
94
94
|
import shlex
|
|
95
95
|
|
|
96
|
-
from ansible.module_utils.common.text.converters import
|
|
96
|
+
from ansible.module_utils.common.text.converters import to_text
|
|
97
97
|
from ansible.plugins.become import BecomeBase
|
|
98
98
|
|
|
99
99
|
|
|
@@ -101,6 +101,8 @@ class BecomeModule(BecomeBase):
|
|
|
101
101
|
|
|
102
102
|
name = 'su'
|
|
103
103
|
|
|
104
|
+
pipelining = False
|
|
105
|
+
|
|
104
106
|
# messages for detecting prompted password issues
|
|
105
107
|
fail = ('Authentication failure',)
|
|
106
108
|
|
|
@@ -139,15 +141,18 @@ class BecomeModule(BecomeBase):
|
|
|
139
141
|
'口令',
|
|
140
142
|
]
|
|
141
143
|
|
|
142
|
-
def check_password_prompt(self, b_output):
|
|
143
|
-
|
|
144
|
-
|
|
144
|
+
def check_password_prompt(self, b_output: bytes) -> bool:
|
|
145
|
+
""" checks if the expected password prompt exists in b_output """
|
|
145
146
|
prompts = self.get_option('prompt_l10n') or self.SU_PROMPT_LOCALIZATIONS
|
|
146
|
-
|
|
147
|
+
password_prompt_strings = "|".join(re.escape(p) for p in prompts)
|
|
147
148
|
# Colon or unicode fullwidth colon
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
149
|
+
prompt_pattern = rf"(?:{password_prompt_strings})\s*[::]"
|
|
150
|
+
match = re.search(prompt_pattern, to_text(b_output), flags=re.IGNORECASE)
|
|
151
|
+
|
|
152
|
+
if match:
|
|
153
|
+
self.prompt = match.group(0) # preserve the actual matched string so we can scrub the output
|
|
154
|
+
|
|
155
|
+
return bool(match)
|
|
151
156
|
|
|
152
157
|
def build_become_command(self, cmd, shell):
|
|
153
158
|
super(BecomeModule, self).build_become_command(cmd, shell)
|
ansible/plugins/become/sudo.py
CHANGED
|
@@ -72,12 +72,25 @@ DOCUMENTATION = """
|
|
|
72
72
|
ini:
|
|
73
73
|
- section: sudo_become_plugin
|
|
74
74
|
key: password
|
|
75
|
+
sudo_chdir:
|
|
76
|
+
description: Directory to change to before invoking sudo; can avoid permission errors when dropping privileges.
|
|
77
|
+
type: string
|
|
78
|
+
required: False
|
|
79
|
+
version_added: '2.19'
|
|
80
|
+
vars:
|
|
81
|
+
- name: ansible_sudo_chdir
|
|
82
|
+
env:
|
|
83
|
+
- name: ANSIBLE_SUDO_CHDIR
|
|
84
|
+
ini:
|
|
85
|
+
- section: sudo_become_plugin
|
|
86
|
+
key: chdir
|
|
75
87
|
"""
|
|
76
88
|
|
|
77
89
|
import re
|
|
78
90
|
import shlex
|
|
79
91
|
|
|
80
92
|
from ansible.plugins.become import BecomeBase
|
|
93
|
+
from ansible.errors import AnsibleError
|
|
81
94
|
|
|
82
95
|
|
|
83
96
|
class BecomeModule(BecomeBase):
|
|
@@ -117,4 +130,10 @@ class BecomeModule(BecomeBase):
|
|
|
117
130
|
if user:
|
|
118
131
|
user = '-u %s' % (user)
|
|
119
132
|
|
|
133
|
+
if chdir := self.get_option('sudo_chdir'):
|
|
134
|
+
try:
|
|
135
|
+
becomecmd = f'{shell.CD} {shlex.quote(chdir)} {shell._SHELL_AND} {becomecmd}'
|
|
136
|
+
except AttributeError as ex:
|
|
137
|
+
raise AnsibleError(f'The {shell._load_name!r} shell plugin does not support sudo chdir. It is missing the {ex.name!r} attribute.')
|
|
138
|
+
|
|
120
139
|
return ' '.join([becomecmd, flags, prompt, user, self._build_success_command(cmd, shell)])
|
|
@@ -18,18 +18,18 @@
|
|
|
18
18
|
from __future__ import annotations
|
|
19
19
|
|
|
20
20
|
import copy
|
|
21
|
-
import errno
|
|
22
21
|
import os
|
|
23
22
|
import tempfile
|
|
24
23
|
import time
|
|
24
|
+
import typing as t
|
|
25
25
|
|
|
26
26
|
from abc import abstractmethod
|
|
27
|
-
from collections
|
|
27
|
+
from collections import abc as c
|
|
28
28
|
|
|
29
29
|
from ansible import constants as C
|
|
30
30
|
from ansible.errors import AnsibleError
|
|
31
31
|
from ansible.module_utils.common.file import S_IRWU_RG_RO
|
|
32
|
-
from ansible.module_utils.common.text.converters import to_bytes
|
|
32
|
+
from ansible.module_utils.common.text.converters import to_bytes
|
|
33
33
|
from ansible.plugins import AnsiblePlugin
|
|
34
34
|
from ansible.plugins.loader import cache_loader
|
|
35
35
|
from ansible.utils.collection_loader import resource_from_fqcr
|
|
@@ -42,37 +42,36 @@ class BaseCacheModule(AnsiblePlugin):
|
|
|
42
42
|
|
|
43
43
|
# Backwards compat only. Just import the global display instead
|
|
44
44
|
_display = display
|
|
45
|
+
_persistent = True
|
|
46
|
+
"""Plugins that do not persist data between runs can set False to bypass schema-version key munging and JSON serialization wrapper."""
|
|
45
47
|
|
|
46
|
-
def __init__(self, *args, **kwargs):
|
|
47
|
-
super(
|
|
48
|
-
self.set_options(var_options=args, direct=kwargs)
|
|
48
|
+
def __init__(self, *args, **kwargs) -> None:
|
|
49
|
+
super().__init__()
|
|
49
50
|
|
|
50
|
-
|
|
51
|
-
def get(self, key):
|
|
52
|
-
pass
|
|
51
|
+
self.set_options(var_options=args, direct=kwargs)
|
|
53
52
|
|
|
54
53
|
@abstractmethod
|
|
55
|
-
def
|
|
54
|
+
def get(self, key: str) -> dict[str, object]:
|
|
56
55
|
pass
|
|
57
56
|
|
|
58
57
|
@abstractmethod
|
|
59
|
-
def
|
|
58
|
+
def set(self, key: str, value: dict[str, object]) -> None:
|
|
60
59
|
pass
|
|
61
60
|
|
|
62
61
|
@abstractmethod
|
|
63
|
-
def
|
|
62
|
+
def keys(self) -> t.Sequence[str]:
|
|
64
63
|
pass
|
|
65
64
|
|
|
66
65
|
@abstractmethod
|
|
67
|
-
def
|
|
66
|
+
def contains(self, key: object) -> bool:
|
|
68
67
|
pass
|
|
69
68
|
|
|
70
69
|
@abstractmethod
|
|
71
|
-
def
|
|
70
|
+
def delete(self, key: str) -> None:
|
|
72
71
|
pass
|
|
73
72
|
|
|
74
73
|
@abstractmethod
|
|
75
|
-
def
|
|
74
|
+
def flush(self) -> None:
|
|
76
75
|
pass
|
|
77
76
|
|
|
78
77
|
|
|
@@ -108,15 +107,15 @@ class BaseFileCacheModule(BaseCacheModule):
|
|
|
108
107
|
if not os.path.exists(self._cache_dir):
|
|
109
108
|
try:
|
|
110
109
|
os.makedirs(self._cache_dir)
|
|
111
|
-
except
|
|
112
|
-
raise AnsibleError("
|
|
110
|
+
except OSError as ex:
|
|
111
|
+
raise AnsibleError(f"Error in {self.plugin_name!r} cache plugin while trying to create cache dir {self._cache_dir!r}.") from ex
|
|
113
112
|
else:
|
|
114
113
|
for x in (os.R_OK, os.W_OK, os.X_OK):
|
|
115
114
|
if not os.access(self._cache_dir, x):
|
|
116
115
|
raise AnsibleError("error in '%s' cache, configured path (%s) does not have necessary permissions (rwx), disabling plugin" % (
|
|
117
116
|
self.plugin_name, self._cache_dir))
|
|
118
117
|
|
|
119
|
-
def _get_cache_file_name(self, key):
|
|
118
|
+
def _get_cache_file_name(self, key: str) -> str:
|
|
120
119
|
prefix = self.get_option('_prefix')
|
|
121
120
|
if prefix:
|
|
122
121
|
cachefile = "%s/%s%s" % (self._cache_dir, prefix, key)
|
|
@@ -144,11 +143,10 @@ class BaseFileCacheModule(BaseCacheModule):
|
|
|
144
143
|
self.delete(key)
|
|
145
144
|
raise AnsibleError("The cache file %s was corrupt, or did not otherwise contain valid data. "
|
|
146
145
|
"It has been removed, so you can re-run your command now." % cachefile)
|
|
147
|
-
except
|
|
148
|
-
display.warning("error in '%s' cache plugin while trying to read %s : %s" % (self.plugin_name, cachefile, to_bytes(e)))
|
|
146
|
+
except FileNotFoundError:
|
|
149
147
|
raise KeyError
|
|
150
|
-
except Exception as
|
|
151
|
-
raise AnsibleError("Error while
|
|
148
|
+
except Exception as ex:
|
|
149
|
+
raise AnsibleError(f"Error while accessing the cache file {cachefile!r}.") from ex
|
|
152
150
|
|
|
153
151
|
return self._cache.get(key)
|
|
154
152
|
|
|
@@ -161,13 +159,13 @@ class BaseFileCacheModule(BaseCacheModule):
|
|
|
161
159
|
try:
|
|
162
160
|
try:
|
|
163
161
|
self._dump(value, tmpfile_path)
|
|
164
|
-
except
|
|
165
|
-
display.
|
|
162
|
+
except OSError as ex:
|
|
163
|
+
display.error_as_warning(f"Error in {self.plugin_name!r} cache plugin while trying to write to {tmpfile_path!r}.", exception=ex)
|
|
166
164
|
try:
|
|
167
165
|
os.rename(tmpfile_path, cachefile)
|
|
168
166
|
os.chmod(cachefile, mode=S_IRWU_RG_RO)
|
|
169
|
-
except
|
|
170
|
-
display.
|
|
167
|
+
except OSError as ex:
|
|
168
|
+
display.error_as_warning(f"Error in {self.plugin_name!r} cache plugin while trying to move {tmpfile_path!r} to {cachefile!r}.", exception=ex)
|
|
171
169
|
finally:
|
|
172
170
|
try:
|
|
173
171
|
os.unlink(tmpfile_path)
|
|
@@ -182,12 +180,12 @@ class BaseFileCacheModule(BaseCacheModule):
|
|
|
182
180
|
cachefile = self._get_cache_file_name(key)
|
|
183
181
|
try:
|
|
184
182
|
st = os.stat(cachefile)
|
|
185
|
-
except
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
183
|
+
except FileNotFoundError:
|
|
184
|
+
return False
|
|
185
|
+
except OSError as ex:
|
|
186
|
+
display.error_as_warning(f"Error in {self.plugin_name!r} cache plugin while trying to stat {cachefile!r}.", exception=ex)
|
|
187
|
+
|
|
188
|
+
return False
|
|
191
189
|
|
|
192
190
|
if time.time() - st.st_mtime <= self._timeout:
|
|
193
191
|
return False
|
|
@@ -224,11 +222,10 @@ class BaseFileCacheModule(BaseCacheModule):
|
|
|
224
222
|
try:
|
|
225
223
|
os.stat(cachefile)
|
|
226
224
|
return True
|
|
227
|
-
except
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
display.warning("error in '%s' cache plugin while trying to stat %s : %s" % (self.plugin_name, cachefile, to_bytes(e)))
|
|
225
|
+
except FileNotFoundError:
|
|
226
|
+
return False
|
|
227
|
+
except OSError as ex:
|
|
228
|
+
display.error_as_warning(f"Error in {self.plugin_name!r} cache plugin while trying to stat {cachefile!r}.", exception=ex)
|
|
232
229
|
|
|
233
230
|
def delete(self, key):
|
|
234
231
|
try:
|
|
@@ -237,7 +234,7 @@ class BaseFileCacheModule(BaseCacheModule):
|
|
|
237
234
|
pass
|
|
238
235
|
try:
|
|
239
236
|
os.remove(self._get_cache_file_name(key))
|
|
240
|
-
except
|
|
237
|
+
except OSError:
|
|
241
238
|
pass # TODO: only pass on non existing?
|
|
242
239
|
|
|
243
240
|
def flush(self):
|
|
@@ -245,14 +242,8 @@ class BaseFileCacheModule(BaseCacheModule):
|
|
|
245
242
|
for key in self.keys():
|
|
246
243
|
self.delete(key)
|
|
247
244
|
|
|
248
|
-
def copy(self):
|
|
249
|
-
ret = dict()
|
|
250
|
-
for key in self.keys():
|
|
251
|
-
ret[key] = self.get(key)
|
|
252
|
-
return ret
|
|
253
|
-
|
|
254
245
|
@abstractmethod
|
|
255
|
-
def _load(self, filepath):
|
|
246
|
+
def _load(self, filepath: str) -> object:
|
|
256
247
|
"""
|
|
257
248
|
Read data from a filepath and return it as a value
|
|
258
249
|
|
|
@@ -271,7 +262,7 @@ class BaseFileCacheModule(BaseCacheModule):
|
|
|
271
262
|
pass
|
|
272
263
|
|
|
273
264
|
@abstractmethod
|
|
274
|
-
def _dump(self, value, filepath):
|
|
265
|
+
def _dump(self, value: object, filepath: str) -> None:
|
|
275
266
|
"""
|
|
276
267
|
Write data to a filepath
|
|
277
268
|
|
|
@@ -281,19 +272,13 @@ class BaseFileCacheModule(BaseCacheModule):
|
|
|
281
272
|
pass
|
|
282
273
|
|
|
283
274
|
|
|
284
|
-
class CachePluginAdjudicator(MutableMapping):
|
|
285
|
-
"""
|
|
286
|
-
|
|
287
|
-
"""
|
|
275
|
+
class CachePluginAdjudicator(c.MutableMapping):
|
|
276
|
+
"""Batch update wrapper around a cache plugin."""
|
|
277
|
+
|
|
288
278
|
def __init__(self, plugin_name='memory', **kwargs):
|
|
289
279
|
self._cache = {}
|
|
290
280
|
self._retrieved = {}
|
|
291
|
-
|
|
292
281
|
self._plugin = cache_loader.get(plugin_name, **kwargs)
|
|
293
|
-
if not self._plugin:
|
|
294
|
-
raise AnsibleError('Unable to load the cache plugin (%s).' % plugin_name)
|
|
295
|
-
|
|
296
|
-
self._plugin_name = plugin_name
|
|
297
282
|
|
|
298
283
|
def update_cache_if_changed(self):
|
|
299
284
|
if self._retrieved != self._cache:
|
|
@@ -302,6 +287,7 @@ class CachePluginAdjudicator(MutableMapping):
|
|
|
302
287
|
def set_cache(self):
|
|
303
288
|
for top_level_cache_key in self._cache.keys():
|
|
304
289
|
self._plugin.set(top_level_cache_key, self._cache[top_level_cache_key])
|
|
290
|
+
|
|
305
291
|
self._retrieved = copy.deepcopy(self._cache)
|
|
306
292
|
|
|
307
293
|
def load_whole_cache(self):
|
|
@@ -309,7 +295,7 @@ class CachePluginAdjudicator(MutableMapping):
|
|
|
309
295
|
self._cache[key] = self._plugin.get(key)
|
|
310
296
|
|
|
311
297
|
def __repr__(self):
|
|
312
|
-
return
|
|
298
|
+
return repr(self._cache)
|
|
313
299
|
|
|
314
300
|
def __iter__(self):
|
|
315
301
|
return iter(self.keys())
|
|
@@ -319,13 +305,10 @@ class CachePluginAdjudicator(MutableMapping):
|
|
|
319
305
|
|
|
320
306
|
def _do_load_key(self, key):
|
|
321
307
|
load = False
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
key not in self._retrieved,
|
|
325
|
-
self._plugin_name != 'memory',
|
|
326
|
-
self._plugin.contains(key),
|
|
327
|
-
]):
|
|
308
|
+
|
|
309
|
+
if key not in self._cache and key not in self._retrieved and self._plugin._persistent and self._plugin.contains(key):
|
|
328
310
|
load = True
|
|
311
|
+
|
|
329
312
|
return load
|
|
330
313
|
|
|
331
314
|
def __getitem__(self, key):
|
|
@@ -336,16 +319,18 @@ class CachePluginAdjudicator(MutableMapping):
|
|
|
336
319
|
pass
|
|
337
320
|
else:
|
|
338
321
|
self._retrieved[key] = self._cache[key]
|
|
322
|
+
|
|
339
323
|
return self._cache[key]
|
|
340
324
|
|
|
341
325
|
def get(self, key, default=None):
|
|
342
326
|
if self._do_load_key(key):
|
|
343
327
|
try:
|
|
344
328
|
self._cache[key] = self._plugin.get(key)
|
|
345
|
-
except KeyError
|
|
329
|
+
except KeyError:
|
|
346
330
|
pass
|
|
347
331
|
else:
|
|
348
332
|
self._retrieved[key] = self._cache[key]
|
|
333
|
+
|
|
349
334
|
return self._cache.get(key, default)
|
|
350
335
|
|
|
351
336
|
def items(self):
|
|
@@ -360,6 +345,7 @@ class CachePluginAdjudicator(MutableMapping):
|
|
|
360
345
|
def pop(self, key, *args):
|
|
361
346
|
if args:
|
|
362
347
|
return self._cache.pop(key, args[0])
|
|
348
|
+
|
|
363
349
|
return self._cache.pop(key)
|
|
364
350
|
|
|
365
351
|
def __delitem__(self, key):
|
|
@@ -368,6 +354,9 @@ class CachePluginAdjudicator(MutableMapping):
|
|
|
368
354
|
def __setitem__(self, key, value):
|
|
369
355
|
self._cache[key] = value
|
|
370
356
|
|
|
357
|
+
def clear(self):
|
|
358
|
+
self.flush()
|
|
359
|
+
|
|
371
360
|
def flush(self):
|
|
372
361
|
self._plugin.flush()
|
|
373
362
|
self._cache = {}
|
ansible/plugins/cache/base.py
CHANGED
|
@@ -18,3 +18,11 @@ from __future__ import annotations
|
|
|
18
18
|
|
|
19
19
|
# moved actual classes to __init__ kept here for backward compat with 3rd parties
|
|
20
20
|
from ansible.plugins.cache import BaseCacheModule, BaseFileCacheModule # pylint: disable=unused-import
|
|
21
|
+
|
|
22
|
+
from ansible.utils.display import Display as _Display
|
|
23
|
+
|
|
24
|
+
_Display().deprecated(
|
|
25
|
+
msg="The `ansible.plugins.cache.base` Python module is deprecated.",
|
|
26
|
+
help_text="Import from `ansible.plugins.cache` instead.",
|
|
27
|
+
version="2.23",
|
|
28
|
+
)
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
from __future__ import annotations
|
|
6
6
|
|
|
7
|
-
DOCUMENTATION =
|
|
7
|
+
DOCUMENTATION = """
|
|
8
8
|
name: jsonfile
|
|
9
9
|
short_description: JSON formatted files.
|
|
10
10
|
description:
|
|
@@ -38,25 +38,19 @@ DOCUMENTATION = '''
|
|
|
38
38
|
- key: fact_caching_timeout
|
|
39
39
|
section: defaults
|
|
40
40
|
type: integer
|
|
41
|
-
|
|
41
|
+
"""
|
|
42
42
|
|
|
43
|
-
import codecs
|
|
44
43
|
import json
|
|
44
|
+
import pathlib
|
|
45
45
|
|
|
46
|
-
from ansible.parsing.ajson import AnsibleJSONEncoder, AnsibleJSONDecoder
|
|
47
46
|
from ansible.plugins.cache import BaseFileCacheModule
|
|
48
47
|
|
|
49
48
|
|
|
50
49
|
class CacheModule(BaseFileCacheModule):
|
|
51
|
-
"""
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
return json.load(f, cls=AnsibleJSONDecoder)
|
|
59
|
-
|
|
60
|
-
def _dump(self, value, filepath):
|
|
61
|
-
with codecs.open(filepath, 'w', encoding='utf-8') as f:
|
|
62
|
-
f.write(json.dumps(value, cls=AnsibleJSONEncoder, sort_keys=True, indent=4))
|
|
50
|
+
"""A caching module backed by json files."""
|
|
51
|
+
|
|
52
|
+
def _load(self, filepath: str) -> object:
|
|
53
|
+
return json.loads(pathlib.Path(filepath).read_text())
|
|
54
|
+
|
|
55
|
+
def _dump(self, value: object, filepath: str) -> None:
|
|
56
|
+
pathlib.Path(filepath).write_text(json.dumps(value))
|