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
|
@@ -4,38 +4,67 @@
|
|
|
4
4
|
from __future__ import annotations
|
|
5
5
|
|
|
6
6
|
import base64
|
|
7
|
+
import dataclasses
|
|
7
8
|
import errno
|
|
8
9
|
import json
|
|
9
10
|
import os
|
|
10
11
|
import pkgutil
|
|
11
12
|
import secrets
|
|
12
13
|
import re
|
|
14
|
+
import typing as t
|
|
15
|
+
|
|
13
16
|
from importlib import import_module
|
|
14
17
|
|
|
15
18
|
from ansible.module_utils.compat.version import LooseVersion
|
|
16
19
|
|
|
17
20
|
from ansible import constants as C
|
|
18
|
-
from ansible.
|
|
19
|
-
from ansible.
|
|
21
|
+
from ansible.module_utils.common.json import Direction, get_module_encoder
|
|
22
|
+
from ansible.errors import AnsibleError, AnsibleFileNotFound
|
|
23
|
+
from ansible.module_utils.common.text.converters import to_bytes, to_text
|
|
24
|
+
from ansible.plugins.become import BecomeBase
|
|
25
|
+
from ansible.plugins.become.runas import BecomeModule as RunasBecomeModule
|
|
20
26
|
from ansible.plugins.loader import ps_module_utils_loader
|
|
21
|
-
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@dataclasses.dataclass(frozen=True)
|
|
30
|
+
class _ExecManifest:
|
|
31
|
+
scripts: dict[str, _ScriptInfo] = dataclasses.field(default_factory=dict)
|
|
32
|
+
actions: list[_ManifestAction] = dataclasses.field(default_factory=list)
|
|
33
|
+
signed_hashlist: list[str] = dataclasses.field(default_factory=list)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@dataclasses.dataclass(frozen=True, kw_only=True)
|
|
37
|
+
class _ScriptInfo:
|
|
38
|
+
content: dataclasses.InitVar[bytes]
|
|
39
|
+
path: str
|
|
40
|
+
script: str = dataclasses.field(init=False)
|
|
41
|
+
|
|
42
|
+
def __post_init__(self, content: bytes) -> None:
|
|
43
|
+
object.__setattr__(self, 'script', base64.b64encode(content).decode())
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@dataclasses.dataclass(frozen=True, kw_only=True)
|
|
47
|
+
class _ManifestAction:
|
|
48
|
+
name: str
|
|
49
|
+
params: dict[str, object] = dataclasses.field(default_factory=dict)
|
|
50
|
+
secure_params: dict[str, object] = dataclasses.field(default_factory=dict)
|
|
22
51
|
|
|
23
52
|
|
|
24
53
|
class PSModuleDepFinder(object):
|
|
25
54
|
|
|
26
|
-
def __init__(self):
|
|
55
|
+
def __init__(self) -> None:
|
|
27
56
|
# This is also used by validate-modules to get a module's required utils in base and a collection.
|
|
28
|
-
self.
|
|
29
|
-
self.
|
|
57
|
+
self.scripts: dict[str, _ScriptInfo] = {}
|
|
58
|
+
self.signed_hashlist: set[str] = set()
|
|
59
|
+
|
|
60
|
+
if builtin_hashlist := _get_powershell_signed_hashlist():
|
|
61
|
+
self.signed_hashlist.add(builtin_hashlist.path)
|
|
62
|
+
self.scripts[builtin_hashlist.path] = builtin_hashlist
|
|
30
63
|
|
|
31
|
-
|
|
32
|
-
# can potentially save time by not adding the type multiple times if it
|
|
33
|
-
# isn't needed
|
|
34
|
-
self.cs_utils_wrapper = dict()
|
|
35
|
-
self.cs_utils_module = dict()
|
|
64
|
+
self._util_deps: dict[str, set[str]] = {}
|
|
36
65
|
|
|
37
|
-
self.ps_version = None
|
|
38
|
-
self.os_version = None
|
|
66
|
+
self.ps_version: str | None = None
|
|
67
|
+
self.os_version: str | None = None
|
|
39
68
|
self.become = False
|
|
40
69
|
|
|
41
70
|
self._re_cs_module = [
|
|
@@ -70,36 +99,58 @@ class PSModuleDepFinder(object):
|
|
|
70
99
|
r'(\.[\w\.]+))(?P<optional>\s+-Optional){0,1}')),
|
|
71
100
|
]
|
|
72
101
|
|
|
73
|
-
self._re_wrapper = re.compile(to_bytes(r'(?i)^#\s*ansiblerequires\s+-wrapper\s+(\w*)'))
|
|
74
102
|
self._re_ps_version = re.compile(to_bytes(r'(?i)^#requires\s+\-version\s+([0-9]+(\.[0-9]+){0,3})$'))
|
|
75
103
|
self._re_os_version = re.compile(to_bytes(r'(?i)^#ansiblerequires\s+\-osversion\s+([0-9]+(\.[0-9]+){0,3})$'))
|
|
76
104
|
self._re_become = re.compile(to_bytes(r'(?i)^#ansiblerequires\s+\-become$'))
|
|
77
105
|
|
|
78
|
-
def
|
|
106
|
+
def scan_exec_script(self, name: str) -> None:
|
|
107
|
+
# scans lib/ansible/executor/powershell for scripts used in the module
|
|
108
|
+
# exec side. It also scans these scripts for any dependencies
|
|
109
|
+
if name in self.scripts:
|
|
110
|
+
return
|
|
111
|
+
|
|
112
|
+
exec_code = _get_powershell_script(name)
|
|
113
|
+
self.scripts[name] = _ScriptInfo(
|
|
114
|
+
content=exec_code,
|
|
115
|
+
path=name,
|
|
116
|
+
)
|
|
117
|
+
self.scan_module(exec_code, powershell=True)
|
|
118
|
+
|
|
119
|
+
def scan_module(
|
|
120
|
+
self,
|
|
121
|
+
module_data: bytes,
|
|
122
|
+
fqn: str | None = None,
|
|
123
|
+
powershell: bool = True,
|
|
124
|
+
) -> set[str]:
|
|
79
125
|
lines = module_data.split(b'\n')
|
|
80
|
-
module_utils = set()
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
126
|
+
module_utils: set[tuple[str, str, bool]] = set()
|
|
127
|
+
|
|
128
|
+
if fqn and fqn.startswith("ansible_collections."):
|
|
129
|
+
submodules = fqn.split('.')
|
|
130
|
+
collection_name = '.'.join(submodules[:3])
|
|
131
|
+
|
|
132
|
+
collection_hashlist = _get_powershell_signed_hashlist(collection_name)
|
|
133
|
+
if collection_hashlist and collection_hashlist.path not in self.signed_hashlist:
|
|
134
|
+
self.signed_hashlist.add(collection_hashlist.path)
|
|
135
|
+
self.scripts[collection_hashlist.path] = collection_hashlist
|
|
85
136
|
|
|
86
137
|
if powershell:
|
|
87
138
|
checks = [
|
|
88
139
|
# PS module contains '#Requires -Module Ansible.ModuleUtils.*'
|
|
89
140
|
# PS module contains '#AnsibleRequires -Powershell Ansible.*' (or collections module_utils ref)
|
|
90
|
-
(self._re_ps_module,
|
|
141
|
+
(self._re_ps_module, ".psm1"),
|
|
91
142
|
# PS module contains '#AnsibleRequires -CSharpUtil Ansible.*' (or collections module_utils ref)
|
|
92
|
-
(self._re_cs_in_ps_module,
|
|
143
|
+
(self._re_cs_in_ps_module, ".cs"),
|
|
93
144
|
]
|
|
94
145
|
else:
|
|
95
146
|
checks = [
|
|
96
147
|
# CS module contains 'using Ansible.*;' or 'using ansible_collections.ns.coll.plugins.module_utils.*;'
|
|
97
|
-
(self._re_cs_module,
|
|
148
|
+
(self._re_cs_module, ".cs"),
|
|
98
149
|
]
|
|
99
150
|
|
|
100
151
|
for line in lines:
|
|
101
|
-
for
|
|
102
|
-
for pattern in
|
|
152
|
+
for patterns, util_extension in checks:
|
|
153
|
+
for pattern in patterns:
|
|
103
154
|
match = pattern.match(line)
|
|
104
155
|
if match:
|
|
105
156
|
# tolerate windows line endings by stripping any remaining
|
|
@@ -107,82 +158,66 @@ class PSModuleDepFinder(object):
|
|
|
107
158
|
module_util_name = to_text(match.group(1).rstrip())
|
|
108
159
|
match_dict = match.groupdict()
|
|
109
160
|
optional = match_dict.get('optional', None) is not None
|
|
110
|
-
|
|
111
|
-
if module_util_name not in check[1].keys():
|
|
112
|
-
module_utils.add((module_util_name, check[2], fqn, optional))
|
|
113
|
-
|
|
161
|
+
module_utils.add((module_util_name, util_extension, optional))
|
|
114
162
|
break
|
|
115
163
|
|
|
116
|
-
if powershell:
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
self.exec_scripts[name] = to_bytes(exec_script)
|
|
161
|
-
self.scan_module(b_data, wrapper=True, powershell=True)
|
|
162
|
-
|
|
163
|
-
def _add_module(self, name, ext, fqn, optional, wrapper=False):
|
|
164
|
-
m = to_text(name)
|
|
165
|
-
|
|
166
|
-
util_fqn = None
|
|
167
|
-
|
|
168
|
-
if m.startswith("Ansible."):
|
|
169
|
-
# Builtin util, use plugin loader to get the data
|
|
170
|
-
mu_path = ps_module_utils_loader.find_plugin(m, ext)
|
|
171
|
-
|
|
172
|
-
if not mu_path:
|
|
164
|
+
if not powershell:
|
|
165
|
+
continue
|
|
166
|
+
|
|
167
|
+
if ps_version_match := self._re_ps_version.match(line):
|
|
168
|
+
self._parse_version_match(ps_version_match, "ps_version")
|
|
169
|
+
|
|
170
|
+
if os_version_match := self._re_os_version.match(line):
|
|
171
|
+
self._parse_version_match(os_version_match, "os_version")
|
|
172
|
+
|
|
173
|
+
# once become is set, no need to keep on checking recursively
|
|
174
|
+
if not self.become and self._re_become.match(line):
|
|
175
|
+
self.become = True
|
|
176
|
+
|
|
177
|
+
dependencies: set[str] = set()
|
|
178
|
+
for name, ext, optional in set(module_utils):
|
|
179
|
+
util_name = self._scan_module_util(name, ext, fqn, optional)
|
|
180
|
+
if util_name:
|
|
181
|
+
dependencies.add(util_name)
|
|
182
|
+
util_deps = self._util_deps[util_name]
|
|
183
|
+
dependencies.update(util_deps)
|
|
184
|
+
|
|
185
|
+
return dependencies
|
|
186
|
+
|
|
187
|
+
def _scan_module_util(
|
|
188
|
+
self,
|
|
189
|
+
name: str,
|
|
190
|
+
ext: str,
|
|
191
|
+
module_fqn: str | None,
|
|
192
|
+
optional: bool,
|
|
193
|
+
) -> str | None:
|
|
194
|
+
util_name: str
|
|
195
|
+
util_path: str
|
|
196
|
+
util_data: bytes
|
|
197
|
+
util_fqn: str | None = None
|
|
198
|
+
|
|
199
|
+
if name.startswith("Ansible."):
|
|
200
|
+
# Builtin util, or the old role module_utils reference.
|
|
201
|
+
util_name = f"{name}{ext}"
|
|
202
|
+
|
|
203
|
+
if util_name in self._util_deps:
|
|
204
|
+
return util_name
|
|
205
|
+
|
|
206
|
+
util_path = ps_module_utils_loader.find_plugin(name, ext)
|
|
207
|
+
if not util_path or not os.path.exists(util_path):
|
|
173
208
|
if optional:
|
|
174
|
-
return
|
|
209
|
+
return None
|
|
175
210
|
|
|
176
|
-
raise AnsibleError(
|
|
177
|
-
|
|
211
|
+
raise AnsibleError(f"Could not find imported module util '{name}'")
|
|
212
|
+
|
|
213
|
+
with open(util_path, 'rb') as mu_file:
|
|
214
|
+
util_data = mu_file.read()
|
|
178
215
|
|
|
179
|
-
module_util_data = to_bytes(_slurp(mu_path))
|
|
180
216
|
else:
|
|
181
217
|
# Collection util, load the package data based on the util import.
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
fqn_submodules = fqn.split('.')
|
|
218
|
+
submodules = name.split(".")
|
|
219
|
+
if name.startswith('.'):
|
|
220
|
+
fqn_submodules = (module_fqn or "").split('.')
|
|
186
221
|
for submodule in submodules:
|
|
187
222
|
if submodule:
|
|
188
223
|
break
|
|
@@ -190,56 +225,70 @@ class PSModuleDepFinder(object):
|
|
|
190
225
|
|
|
191
226
|
submodules = fqn_submodules + [s for s in submodules if s]
|
|
192
227
|
|
|
193
|
-
|
|
194
|
-
|
|
228
|
+
util_package = '.'.join(submodules[:-1])
|
|
229
|
+
util_resource_name = f"{submodules[-1]}{ext}"
|
|
230
|
+
util_fqn = f"{util_package}.{submodules[-1]}"
|
|
231
|
+
util_name = f"{util_package}.{util_resource_name}"
|
|
232
|
+
|
|
233
|
+
if util_name in self._util_deps:
|
|
234
|
+
return util_name
|
|
195
235
|
|
|
196
236
|
try:
|
|
197
|
-
module_util = import_module(
|
|
198
|
-
|
|
199
|
-
if
|
|
237
|
+
module_util = import_module(util_package)
|
|
238
|
+
util_code = pkgutil.get_data(util_package, util_resource_name)
|
|
239
|
+
if util_code is None:
|
|
200
240
|
raise ImportError("No package data found")
|
|
201
|
-
|
|
202
|
-
module_util_data = to_bytes(pkg_data, errors='surrogate_or_strict')
|
|
203
|
-
util_fqn = to_text("%s.%s " % (n_package_name, submodules[-1]), errors='surrogate_or_strict')
|
|
241
|
+
util_data = util_code
|
|
204
242
|
|
|
205
243
|
# Get the path of the util which is required for coverage collection.
|
|
206
244
|
resource_paths = list(module_util.__path__)
|
|
207
245
|
if len(resource_paths) != 1:
|
|
208
246
|
# This should never happen with a collection but we are just being defensive about it.
|
|
209
|
-
raise AnsibleError("Internal error: Referenced module_util package '
|
|
210
|
-
"import locations when we only expect 1."
|
|
211
|
-
|
|
247
|
+
raise AnsibleError(f"Internal error: Referenced module_util package '{util_package}' contains 0 "
|
|
248
|
+
"or multiple import locations when we only expect 1.")
|
|
249
|
+
|
|
250
|
+
util_path = os.path.join(resource_paths[0], util_resource_name)
|
|
212
251
|
except (ImportError, OSError) as err:
|
|
213
252
|
if getattr(err, "errno", errno.ENOENT) == errno.ENOENT:
|
|
214
253
|
if optional:
|
|
215
|
-
return
|
|
254
|
+
return None
|
|
216
255
|
|
|
217
|
-
raise AnsibleError(
|
|
218
|
-
% to_native(m))
|
|
256
|
+
raise AnsibleError(f"Could not find collection imported module support code for '{name}'")
|
|
219
257
|
|
|
220
258
|
else:
|
|
221
259
|
raise
|
|
222
260
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
self.scan_module(
|
|
261
|
+
# This is important to be set before scan_module is called to avoid
|
|
262
|
+
# recursive dependencies.
|
|
263
|
+
self.scripts[util_name] = _ScriptInfo(
|
|
264
|
+
content=util_data,
|
|
265
|
+
path=util_path,
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
# It is important this is set before calling scan_module to ensure
|
|
269
|
+
# recursive dependencies don't result in an infinite loop.
|
|
270
|
+
dependencies = self._util_deps[util_name] = set()
|
|
271
|
+
|
|
272
|
+
util_deps = self.scan_module(util_data, fqn=util_fqn, powershell=(ext == ".psm1"))
|
|
273
|
+
dependencies.update(util_deps)
|
|
274
|
+
for dep in dependencies:
|
|
275
|
+
if dep_list := self._util_deps.get(dep):
|
|
276
|
+
dependencies.update(dep_list)
|
|
277
|
+
|
|
278
|
+
if ext == ".cs":
|
|
279
|
+
# Any C# code requires the AddType.psm1 module to load.
|
|
280
|
+
dependencies.add("Ansible.ModuleUtils.AddType.psm1")
|
|
281
|
+
self._scan_module_util("Ansible.ModuleUtils.AddType", ".psm1", None, False)
|
|
235
282
|
|
|
236
|
-
|
|
283
|
+
return util_name
|
|
284
|
+
|
|
285
|
+
def _parse_version_match(self, match: re.Match, attribute: str) -> None:
|
|
237
286
|
new_version = to_text(match.group(1)).rstrip()
|
|
238
287
|
|
|
239
288
|
# PowerShell cannot cast a string of "1" to Version, it must have at
|
|
240
289
|
# least the major.minor for it to be valid so we append 0
|
|
241
290
|
if match.group(2) is None:
|
|
242
|
-
new_version = "
|
|
291
|
+
new_version = f"{new_version}.0"
|
|
243
292
|
|
|
244
293
|
existing_version = getattr(self, attribute, None)
|
|
245
294
|
if existing_version is None:
|
|
@@ -250,152 +299,307 @@ class PSModuleDepFinder(object):
|
|
|
250
299
|
setattr(self, attribute, new_version)
|
|
251
300
|
|
|
252
301
|
|
|
253
|
-
def
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
302
|
+
def _bootstrap_powershell_script(
|
|
303
|
+
name: str,
|
|
304
|
+
parameters: dict[str, t.Any] | None = None,
|
|
305
|
+
*,
|
|
306
|
+
has_input: bool = False,
|
|
307
|
+
) -> tuple[str, bytes]:
|
|
308
|
+
"""Build bootstrap wrapper for specified script.
|
|
309
|
+
|
|
310
|
+
Builds the bootstrap wrapper and input needed to run the specified executor
|
|
311
|
+
PowerShell script specified.
|
|
312
|
+
|
|
313
|
+
:param name: The name of the PowerShell script to run.
|
|
314
|
+
:param parameters: The parameters to pass to the script.
|
|
315
|
+
:param has_input: The script will be provided with input data.
|
|
316
|
+
:return: The bootstrap wrapper and input to provide to it.
|
|
317
|
+
"""
|
|
318
|
+
exec_manifest = _ExecManifest()
|
|
319
|
+
|
|
320
|
+
script = _get_powershell_script(name)
|
|
321
|
+
exec_manifest.scripts[name] = _ScriptInfo(
|
|
322
|
+
content=script,
|
|
323
|
+
path=name,
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
exec_manifest.actions.append(
|
|
327
|
+
_ManifestAction(
|
|
328
|
+
name=name,
|
|
329
|
+
params=parameters or {},
|
|
330
|
+
)
|
|
331
|
+
)
|
|
332
|
+
|
|
333
|
+
if hashlist := _get_powershell_signed_hashlist():
|
|
334
|
+
exec_manifest.signed_hashlist.append(hashlist.path)
|
|
335
|
+
exec_manifest.scripts[hashlist.path] = hashlist
|
|
336
|
+
|
|
337
|
+
bootstrap_wrapper = _get_powershell_script("bootstrap_wrapper.ps1")
|
|
338
|
+
bootstrap_input = _get_bootstrap_input(exec_manifest)
|
|
339
|
+
if has_input:
|
|
340
|
+
bootstrap_input += b"\n\0\0\0\0\n"
|
|
341
|
+
|
|
342
|
+
return bootstrap_wrapper.decode(), bootstrap_input
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
def _get_powershell_script(
|
|
346
|
+
name: str,
|
|
347
|
+
) -> bytes:
|
|
348
|
+
"""Get the requested PowerShell script.
|
|
349
|
+
|
|
350
|
+
Gets the script stored in the ansible.executore.powershell package.
|
|
351
|
+
|
|
352
|
+
:param name: The name of the PowerShell script to retrieve.
|
|
353
|
+
:return: The contents of the requested PowerShell script as a byte string.
|
|
354
|
+
"""
|
|
355
|
+
package_name = 'ansible.executor.powershell'
|
|
356
|
+
|
|
357
|
+
code = pkgutil.get_data(package_name, name)
|
|
358
|
+
if code is None:
|
|
359
|
+
raise AnsibleFileNotFound(f"Could not find powershell script '{package_name}.{name}'")
|
|
360
|
+
|
|
361
|
+
try:
|
|
362
|
+
sig_data = pkgutil.get_data(package_name, f"{name}.authenticode")
|
|
363
|
+
except FileNotFoundError:
|
|
364
|
+
sig_data = None
|
|
365
|
+
|
|
366
|
+
if sig_data:
|
|
367
|
+
code = code + b"\r\n" + b"\r\n".join(sig_data.splitlines()) + b"\r\n"
|
|
368
|
+
|
|
369
|
+
return code
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
def _create_powershell_wrapper(
|
|
373
|
+
*,
|
|
374
|
+
name: str,
|
|
375
|
+
module_data: bytes,
|
|
376
|
+
module_path: str,
|
|
377
|
+
module_args: dict[t.Any, t.Any],
|
|
378
|
+
environment: dict[str, str],
|
|
379
|
+
async_timeout: int,
|
|
380
|
+
become_plugin: BecomeBase | None,
|
|
381
|
+
substyle: t.Literal["powershell", "script"],
|
|
382
|
+
task_vars: dict[str, t.Any],
|
|
383
|
+
profile: str,
|
|
384
|
+
) -> bytes:
|
|
385
|
+
"""Creates module or script wrapper for PowerShell.
|
|
386
|
+
|
|
387
|
+
Creates the input data to provide to bootstrap_wrapper.ps1 when running a
|
|
388
|
+
PowerShell module or script.
|
|
389
|
+
|
|
390
|
+
:param name: The fully qualified name of the module or script filename (without extension).
|
|
391
|
+
:param module_data: The data of the module or script.
|
|
392
|
+
:param module_path: The path of the module or script.
|
|
393
|
+
:param module_args: The arguments to pass to the module or script.
|
|
394
|
+
:param environment: The environment variables to set when running the module or script.
|
|
395
|
+
:param async_timeout: The timeout to use for async execution or 0 for no async.
|
|
396
|
+
:param become_plugin: The become plugin to use for privilege escalation or None for no become.
|
|
397
|
+
:param substyle: The substyle of the module or script to run [powershell or script].
|
|
398
|
+
:param task_vars: The task variables used on the task.
|
|
399
|
+
|
|
400
|
+
:return: The input data for bootstrap_wrapper.ps1 as a byte string.
|
|
401
|
+
"""
|
|
402
|
+
|
|
403
|
+
actions: list[_ManifestAction] = []
|
|
295
404
|
finder = PSModuleDepFinder()
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
module_entry=to_text(base64.b64encode(b_module_data)),
|
|
304
|
-
powershell_modules=dict(),
|
|
305
|
-
csharp_utils=dict(),
|
|
306
|
-
csharp_utils_module=list(), # csharp_utils only required by a module
|
|
307
|
-
module_args=module_args,
|
|
308
|
-
actions=[module_wrapper],
|
|
309
|
-
environment=environment,
|
|
310
|
-
encoded_output=False,
|
|
405
|
+
finder.scan_exec_script('module_wrapper.ps1')
|
|
406
|
+
|
|
407
|
+
ext = os.path.splitext(module_path)[1]
|
|
408
|
+
name_with_ext = f"{name}{ext}"
|
|
409
|
+
finder.scripts[name_with_ext] = _ScriptInfo(
|
|
410
|
+
content=module_data,
|
|
411
|
+
path=module_path,
|
|
311
412
|
)
|
|
312
|
-
|
|
413
|
+
|
|
414
|
+
module_params: dict[str, t.Any] = {
|
|
415
|
+
'Script': name_with_ext,
|
|
416
|
+
'Environment': environment,
|
|
417
|
+
}
|
|
418
|
+
if substyle != 'script':
|
|
419
|
+
module_deps = finder.scan_module(
|
|
420
|
+
module_data,
|
|
421
|
+
fqn=name,
|
|
422
|
+
powershell=True,
|
|
423
|
+
)
|
|
424
|
+
cs_deps = []
|
|
425
|
+
ps_deps = []
|
|
426
|
+
for dep in module_deps:
|
|
427
|
+
if dep.endswith('.cs'):
|
|
428
|
+
cs_deps.append(dep)
|
|
429
|
+
else:
|
|
430
|
+
ps_deps.append(dep)
|
|
431
|
+
|
|
432
|
+
module_params |= {
|
|
433
|
+
'Variables': [
|
|
434
|
+
{
|
|
435
|
+
'Name': 'complex_args',
|
|
436
|
+
'Value': _prepare_module_args(module_args, profile),
|
|
437
|
+
'Scope': 'Global',
|
|
438
|
+
},
|
|
439
|
+
],
|
|
440
|
+
'CSharpModules': cs_deps,
|
|
441
|
+
'PowerShellModules': ps_deps,
|
|
442
|
+
'ForModule': True,
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
if become_plugin or finder.become:
|
|
446
|
+
become_script = 'become_wrapper.ps1'
|
|
447
|
+
become_params: dict[str, t.Any] = {
|
|
448
|
+
'BecomeUser': 'SYSTEM',
|
|
449
|
+
}
|
|
450
|
+
become_secure_params: dict[str, t.Any] = {}
|
|
451
|
+
|
|
452
|
+
if become_plugin:
|
|
453
|
+
if not isinstance(become_plugin, RunasBecomeModule):
|
|
454
|
+
msg = f"Become plugin {become_plugin.name} is not supported by the Windows exec wrapper. Make sure to set the become method to runas."
|
|
455
|
+
raise AnsibleError(msg)
|
|
456
|
+
|
|
457
|
+
become_script, become_params, become_secure_params = become_plugin._build_powershell_wrapper_action()
|
|
458
|
+
|
|
459
|
+
finder.scan_exec_script('exec_wrapper.ps1')
|
|
460
|
+
finder.scan_exec_script(become_script)
|
|
461
|
+
actions.append(
|
|
462
|
+
_ManifestAction(
|
|
463
|
+
name=become_script,
|
|
464
|
+
params=become_params,
|
|
465
|
+
secure_params=become_secure_params,
|
|
466
|
+
)
|
|
467
|
+
)
|
|
313
468
|
|
|
314
469
|
if async_timeout > 0:
|
|
315
|
-
finder.scan_exec_script('
|
|
316
|
-
finder.scan_exec_script('
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
coverage_manifest = dict(
|
|
346
|
-
module_path=module_path,
|
|
347
|
-
module_util_paths=dict(),
|
|
348
|
-
output=None,
|
|
349
|
-
)
|
|
470
|
+
finder.scan_exec_script('bootstrap_wrapper.ps1')
|
|
471
|
+
finder.scan_exec_script('exec_wrapper.ps1')
|
|
472
|
+
|
|
473
|
+
async_dir = environment.get('ANSIBLE_ASYNC_DIR', None)
|
|
474
|
+
if not async_dir:
|
|
475
|
+
raise AnsibleError("The environment variable 'ANSIBLE_ASYNC_DIR' is not set.")
|
|
476
|
+
|
|
477
|
+
finder.scan_exec_script('async_wrapper.ps1')
|
|
478
|
+
actions.append(
|
|
479
|
+
_ManifestAction(
|
|
480
|
+
name='async_wrapper.ps1',
|
|
481
|
+
params={
|
|
482
|
+
'AsyncDir': async_dir,
|
|
483
|
+
'AsyncJid': f'j{secrets.randbelow(999999999999)}',
|
|
484
|
+
'StartupTimeout': C.config.get_config_value("WIN_ASYNC_STARTUP_TIMEOUT", variables=task_vars),
|
|
485
|
+
},
|
|
486
|
+
)
|
|
487
|
+
)
|
|
488
|
+
|
|
489
|
+
finder.scan_exec_script('async_watchdog.ps1')
|
|
490
|
+
actions.append(
|
|
491
|
+
_ManifestAction(
|
|
492
|
+
name='async_watchdog.ps1',
|
|
493
|
+
params={
|
|
494
|
+
'Timeout': async_timeout,
|
|
495
|
+
},
|
|
496
|
+
)
|
|
497
|
+
)
|
|
498
|
+
|
|
350
499
|
coverage_output = C.config.get_config_value('COVERAGE_REMOTE_OUTPUT', variables=task_vars)
|
|
351
500
|
if coverage_output and substyle == 'powershell':
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
501
|
+
path_filter = C.config.get_config_value('COVERAGE_REMOTE_PATHS', variables=task_vars)
|
|
502
|
+
|
|
503
|
+
finder.scan_exec_script('coverage_wrapper.ps1')
|
|
504
|
+
actions.append(
|
|
505
|
+
_ManifestAction(
|
|
506
|
+
name='coverage_wrapper.ps1',
|
|
507
|
+
params={
|
|
508
|
+
'ModuleName': name_with_ext,
|
|
509
|
+
'OutputPath': coverage_output,
|
|
510
|
+
'PathFilter': path_filter,
|
|
511
|
+
},
|
|
512
|
+
)
|
|
513
|
+
)
|
|
514
|
+
|
|
515
|
+
actions.append(
|
|
516
|
+
_ManifestAction(
|
|
517
|
+
name='module_wrapper.ps1',
|
|
518
|
+
params=module_params,
|
|
519
|
+
),
|
|
520
|
+
)
|
|
521
|
+
|
|
522
|
+
temp_path: str | None = None
|
|
523
|
+
for temp_key in ['_ansible_tmpdir', '_ansible_remote_tmp']:
|
|
524
|
+
if temp_value := module_args.get(temp_key, None):
|
|
525
|
+
temp_path = temp_value
|
|
526
|
+
break
|
|
527
|
+
|
|
528
|
+
exec_manifest = _ExecManifest(
|
|
529
|
+
scripts=finder.scripts,
|
|
530
|
+
actions=actions,
|
|
531
|
+
signed_hashlist=list(finder.signed_hashlist),
|
|
532
|
+
)
|
|
533
|
+
|
|
534
|
+
return _get_bootstrap_input(
|
|
535
|
+
exec_manifest,
|
|
536
|
+
min_os_version=finder.os_version,
|
|
537
|
+
min_ps_version=finder.ps_version,
|
|
538
|
+
temp_path=temp_path,
|
|
539
|
+
)
|
|
540
|
+
|
|
541
|
+
|
|
542
|
+
def _get_bootstrap_input(
|
|
543
|
+
manifest: _ExecManifest,
|
|
544
|
+
min_os_version: str | None = None,
|
|
545
|
+
min_ps_version: str | None = None,
|
|
546
|
+
temp_path: str | None = None,
|
|
547
|
+
) -> bytes:
|
|
548
|
+
"""Gets the input for bootstrap_wrapper.ps1
|
|
549
|
+
|
|
550
|
+
Gets the input needed to send to bootstrap_wrapper.ps1 to run code through
|
|
551
|
+
exec_wrapper.ps1.
|
|
552
|
+
|
|
553
|
+
:param manifest: The exec wrapper manifest of scripts and actions to run.
|
|
554
|
+
:param min_os_version: The minimum OS version required to run the scripts.
|
|
555
|
+
:param min_ps_version: The minimum PowerShell version required to run the scripts.
|
|
556
|
+
:param temp_path: The temporary path to use for the scripts if needed.
|
|
557
|
+
:return: The input for bootstrap_wrapper.ps1 as a byte string.
|
|
558
|
+
"""
|
|
559
|
+
bootstrap_manifest = {
|
|
560
|
+
'name': 'exec_wrapper',
|
|
561
|
+
'script': _get_powershell_script("exec_wrapper.ps1").decode(),
|
|
562
|
+
'params': {
|
|
563
|
+
'MinOSVersion': min_os_version,
|
|
564
|
+
'MinPSVersion': min_ps_version,
|
|
565
|
+
'TempPath': temp_path,
|
|
566
|
+
},
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
bootstrap_input = json.dumps(bootstrap_manifest, ensure_ascii=True)
|
|
570
|
+
exec_input = json.dumps(dataclasses.asdict(manifest))
|
|
571
|
+
return f"{bootstrap_input}\n\0\0\0\0\n{exec_input}".encode()
|
|
572
|
+
|
|
573
|
+
|
|
574
|
+
def _prepare_module_args(module_args: dict[str, t.Any], profile: str) -> dict[str, t.Any]:
|
|
575
|
+
"""
|
|
576
|
+
Serialize the module args with the specified profile and deserialize them with the Python built-in JSON decoder.
|
|
577
|
+
This is used to facilitate serializing module args with a different encoder (profile) than is used for the manifest.
|
|
578
|
+
"""
|
|
579
|
+
encoder = get_module_encoder(profile, Direction.CONTROLLER_TO_MODULE)
|
|
580
|
+
|
|
581
|
+
return json.loads(json.dumps(module_args, cls=encoder))
|
|
582
|
+
|
|
583
|
+
|
|
584
|
+
def _get_powershell_signed_hashlist(
|
|
585
|
+
collection: str | None = None,
|
|
586
|
+
) -> _ScriptInfo | None:
|
|
587
|
+
"""Gets the signed hashlist script stored in either the Ansible package or for
|
|
588
|
+
the collection specified.
|
|
589
|
+
|
|
590
|
+
:param collection: The collection namespace to get the signed hashlist for or None for the builtin.
|
|
591
|
+
:return: The _ScriptInfo payload of the signed hashlist script if found, None if not.
|
|
592
|
+
"""
|
|
593
|
+
resource = 'ansible.config' if collection is None else f"{collection}.meta"
|
|
594
|
+
signature_file = 'powershell_signatures.psd1'
|
|
595
|
+
|
|
596
|
+
try:
|
|
597
|
+
sig_data = pkgutil.get_data(resource, signature_file)
|
|
598
|
+
except FileNotFoundError:
|
|
599
|
+
sig_data = None
|
|
600
|
+
|
|
601
|
+
if sig_data:
|
|
602
|
+
resource_path = f"{resource}.{signature_file}"
|
|
603
|
+
return _ScriptInfo(content=sig_data, path=resource_path)
|
|
604
|
+
|
|
605
|
+
return None
|