ansible-core 2.18.5rc1__py3-none-any.whl → 2.19.0b2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ansible/_internal/__init__.py +53 -0
- ansible/_internal/_ansiballz.py +265 -0
- ansible/_internal/_collection_proxy.py +47 -0
- ansible/_internal/_datatag/__init__.py +0 -0
- ansible/_internal/_datatag/_tags.py +130 -0
- ansible/_internal/_datatag/_utils.py +19 -0
- ansible/_internal/_datatag/_wrappers.py +33 -0
- ansible/_internal/_errors/__init__.py +0 -0
- ansible/_internal/_errors/_captured.py +128 -0
- ansible/_internal/_errors/_handler.py +91 -0
- ansible/_internal/_errors/_utils.py +310 -0
- ansible/_internal/_json/__init__.py +203 -0
- ansible/_internal/_json/_legacy_encoder.py +34 -0
- ansible/_internal/_json/_profiles/__init__.py +0 -0
- ansible/_internal/_json/_profiles/_cache_persistence.py +55 -0
- ansible/_internal/_json/_profiles/_inventory_legacy.py +40 -0
- ansible/_internal/_json/_profiles/_legacy.py +197 -0
- ansible/_internal/_locking.py +21 -0
- ansible/_internal/_plugins/__init__.py +0 -0
- ansible/_internal/_plugins/_cache.py +57 -0
- ansible/_internal/_task.py +78 -0
- ansible/_internal/_templating/__init__.py +10 -0
- ansible/_internal/_templating/_access.py +86 -0
- ansible/_internal/_templating/_chain_templar.py +63 -0
- ansible/_internal/_templating/_datatag.py +95 -0
- ansible/_internal/_templating/_engine.py +588 -0
- ansible/_internal/_templating/_errors.py +28 -0
- ansible/_internal/_templating/_jinja_bits.py +1066 -0
- ansible/_internal/_templating/_jinja_common.py +332 -0
- ansible/_internal/_templating/_jinja_patches.py +44 -0
- ansible/_internal/_templating/_jinja_plugins.py +345 -0
- ansible/_internal/_templating/_lazy_containers.py +633 -0
- ansible/_internal/_templating/_marker_behaviors.py +103 -0
- ansible/_internal/_templating/_transform.py +63 -0
- ansible/_internal/_templating/_utils.py +107 -0
- ansible/_internal/_wrapt.py +1052 -0
- ansible/_internal/_yaml/__init__.py +0 -0
- ansible/_internal/_yaml/_constructor.py +240 -0
- ansible/_internal/_yaml/_dumper.py +62 -0
- ansible/_internal/_yaml/_errors.py +166 -0
- ansible/_internal/_yaml/_loader.py +66 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/README.md +11 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/action/debug.py +36 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/apply_trust.py +19 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/dump_object.py +18 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/finalize.py +16 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/origin.py +18 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/python_literal_eval.py +24 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/python_literal_eval.yml +33 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/tag_names.py +16 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/true_type.py +17 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/unmask.py +49 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/lookup/config.py +21 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/lookup/config.yml +2 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged.py +15 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged.yml +19 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged_with.py +18 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged_with.yml +19 -0
- ansible/cli/__init__.py +159 -89
- ansible/cli/_ssh_askpass.py +47 -0
- ansible/cli/adhoc.py +14 -7
- ansible/cli/arguments/option_helpers.py +154 -7
- ansible/cli/config.py +43 -68
- ansible/cli/console.py +10 -8
- ansible/cli/doc.py +62 -53
- ansible/cli/galaxy.py +27 -20
- ansible/cli/inventory.py +28 -26
- ansible/cli/playbook.py +4 -12
- ansible/cli/pull.py +51 -11
- ansible/cli/scripts/ansible_connection_cli_stub.py +7 -7
- ansible/cli/vault.py +12 -11
- ansible/compat/__init__.py +2 -2
- ansible/config/base.yml +166 -112
- ansible/config/manager.py +52 -49
- ansible/constants.py +3 -4
- ansible/errors/__init__.py +277 -235
- ansible/executor/interpreter_discovery.py +28 -149
- ansible/executor/module_common.py +426 -493
- ansible/executor/play_iterator.py +22 -27
- ansible/executor/playbook_executor.py +11 -11
- ansible/executor/powershell/async_watchdog.ps1 +97 -102
- ansible/executor/powershell/async_wrapper.ps1 +202 -151
- ansible/executor/powershell/become_wrapper.ps1 +89 -144
- ansible/executor/powershell/bootstrap_wrapper.ps1 +24 -9
- ansible/executor/powershell/coverage_wrapper.ps1 +82 -135
- ansible/executor/powershell/exec_wrapper.ps1 +462 -196
- ansible/executor/powershell/module_manifest.py +417 -265
- ansible/executor/powershell/module_wrapper.ps1 +169 -186
- ansible/executor/powershell/psrp_fetch_file.ps1 +41 -0
- ansible/executor/powershell/psrp_put_file.ps1 +122 -0
- ansible/executor/powershell/winrm_fetch_file.ps1 +46 -0
- ansible/executor/powershell/winrm_put_file.ps1 +36 -0
- ansible/executor/process/worker.py +161 -96
- ansible/executor/stats.py +5 -5
- ansible/executor/task_executor.py +268 -258
- ansible/executor/task_queue_manager.py +124 -90
- ansible/executor/task_result.py +183 -78
- ansible/galaxy/__init__.py +2 -2
- ansible/galaxy/api.py +22 -18
- ansible/galaxy/collection/__init__.py +1 -1
- ansible/galaxy/collection/concrete_artifact_manager.py +8 -11
- ansible/galaxy/dependency_resolution/dataclasses.py +14 -4
- ansible/galaxy/dependency_resolution/providers.py +1 -1
- ansible/galaxy/dependency_resolution/reporters.py +81 -0
- ansible/galaxy/role.py +4 -8
- ansible/galaxy/token.py +28 -21
- ansible/inventory/data.py +47 -57
- ansible/inventory/group.py +44 -72
- ansible/inventory/helpers.py +9 -0
- ansible/inventory/host.py +32 -54
- ansible/inventory/manager.py +78 -34
- ansible/keyword_desc.yml +1 -1
- ansible/module_utils/_internal/__init__.py +55 -0
- ansible/module_utils/_internal/_ambient_context.py +58 -0
- ansible/module_utils/_internal/_ansiballz.py +133 -0
- ansible/module_utils/_internal/_concurrent/_daemon_threading.py +1 -0
- ansible/module_utils/_internal/_dataclass_annotation_patch.py +64 -0
- ansible/module_utils/_internal/_dataclass_validation.py +217 -0
- ansible/module_utils/_internal/_datatag/__init__.py +928 -0
- ansible/module_utils/_internal/_datatag/_tags.py +38 -0
- ansible/module_utils/_internal/_debugging.py +31 -0
- ansible/module_utils/_internal/_errors.py +30 -0
- ansible/module_utils/_internal/_json/__init__.py +63 -0
- ansible/module_utils/_internal/_json/_legacy_encoder.py +26 -0
- ansible/module_utils/_internal/_json/_profiles/__init__.py +410 -0
- ansible/module_utils/_internal/_json/_profiles/_fallback_to_str.py +73 -0
- ansible/module_utils/_internal/_json/_profiles/_module_legacy_c2m.py +31 -0
- ansible/module_utils/_internal/_json/_profiles/_module_legacy_m2c.py +35 -0
- ansible/module_utils/_internal/_json/_profiles/_module_modern_c2m.py +35 -0
- ansible/module_utils/_internal/_json/_profiles/_module_modern_m2c.py +33 -0
- ansible/module_utils/_internal/_json/_profiles/_tagless.py +50 -0
- ansible/module_utils/_internal/_patches/__init__.py +66 -0
- ansible/module_utils/_internal/_patches/_dataclass_annotation_patch.py +55 -0
- ansible/module_utils/_internal/_patches/_socket_patch.py +34 -0
- ansible/module_utils/_internal/_patches/_sys_intern_patch.py +34 -0
- ansible/module_utils/_internal/_plugin_exec_context.py +49 -0
- ansible/module_utils/_internal/_testing.py +0 -0
- ansible/module_utils/_internal/_traceback.py +89 -0
- ansible/module_utils/ansible_release.py +2 -2
- ansible/module_utils/api.py +1 -2
- ansible/module_utils/basic.py +152 -120
- ansible/module_utils/common/_utils.py +24 -28
- ansible/module_utils/common/collections.py +1 -2
- ansible/module_utils/common/dict_transformations.py +2 -2
- ansible/module_utils/common/file.py +2 -2
- ansible/module_utils/common/json.py +90 -84
- ansible/module_utils/common/locale.py +2 -2
- ansible/module_utils/common/messages.py +108 -0
- ansible/module_utils/common/parameters.py +27 -24
- ansible/module_utils/common/process.py +2 -2
- ansible/module_utils/common/respawn.py +41 -19
- ansible/module_utils/common/sentinel.py +66 -0
- ansible/module_utils/common/sys_info.py +8 -8
- ansible/module_utils/common/text/converters.py +16 -37
- ansible/module_utils/common/validation.py +35 -24
- ansible/module_utils/common/warnings.py +86 -25
- ansible/module_utils/common/yaml.py +29 -3
- ansible/module_utils/compat/datetime.py +33 -21
- ansible/module_utils/compat/paramiko.py +21 -10
- ansible/module_utils/compat/typing.py +6 -5
- ansible/module_utils/connection.py +2 -2
- ansible/module_utils/csharp/Ansible.Basic.cs +14 -11
- ansible/module_utils/csharp/Ansible.Become.cs +1 -0
- ansible/module_utils/csharp/Ansible._Async.cs +517 -0
- ansible/module_utils/datatag.py +46 -0
- ansible/module_utils/distro/__init__.py +2 -2
- ansible/module_utils/facts/ansible_collector.py +4 -5
- ansible/module_utils/facts/collector.py +13 -14
- ansible/module_utils/facts/compat.py +4 -4
- ansible/module_utils/facts/default_collectors.py +1 -1
- ansible/module_utils/facts/hardware/aix.py +34 -0
- ansible/module_utils/facts/hardware/base.py +1 -1
- ansible/module_utils/facts/hardware/darwin.py +1 -3
- ansible/module_utils/facts/hardware/freebsd.py +2 -2
- ansible/module_utils/facts/hardware/linux.py +4 -4
- ansible/module_utils/facts/namespace.py +1 -1
- ansible/module_utils/facts/network/base.py +1 -1
- ansible/module_utils/facts/network/fc_wwn.py +1 -2
- ansible/module_utils/facts/network/iscsi.py +1 -2
- ansible/module_utils/facts/network/nvme.py +1 -2
- ansible/module_utils/facts/other/facter.py +1 -2
- ansible/module_utils/facts/other/ohai.py +2 -3
- ansible/module_utils/facts/system/apparmor.py +1 -2
- ansible/module_utils/facts/system/caps.py +1 -1
- ansible/module_utils/facts/system/chroot.py +1 -2
- ansible/module_utils/facts/system/cmdline.py +1 -2
- ansible/module_utils/facts/system/date_time.py +5 -3
- ansible/module_utils/facts/system/distribution.py +9 -8
- ansible/module_utils/facts/system/dns.py +1 -1
- ansible/module_utils/facts/system/env.py +1 -2
- ansible/module_utils/facts/system/fips.py +7 -20
- ansible/module_utils/facts/system/loadavg.py +1 -2
- ansible/module_utils/facts/system/local.py +1 -2
- ansible/module_utils/facts/system/lsb.py +1 -2
- ansible/module_utils/facts/system/pkg_mgr.py +1 -2
- ansible/module_utils/facts/system/platform.py +1 -2
- ansible/module_utils/facts/system/python.py +1 -2
- ansible/module_utils/facts/system/selinux.py +1 -1
- ansible/module_utils/facts/system/service_mgr.py +1 -2
- ansible/module_utils/facts/system/ssh_pub_keys.py +1 -1
- ansible/module_utils/facts/system/systemd.py +1 -1
- ansible/module_utils/facts/system/user.py +1 -2
- ansible/module_utils/facts/utils.py +3 -3
- ansible/module_utils/facts/virtual/base.py +1 -1
- ansible/module_utils/facts/virtual/sunos.py +3 -15
- ansible/module_utils/facts/virtual/sysctl.py +3 -16
- ansible/module_utils/json_utils.py +2 -2
- ansible/module_utils/parsing/convert_bool.py +1 -1
- ansible/module_utils/service.py +18 -21
- ansible/module_utils/splitter.py +7 -7
- ansible/module_utils/testing.py +31 -0
- ansible/module_utils/urls.py +60 -31
- ansible/modules/add_host.py +4 -4
- ansible/modules/apt.py +60 -46
- ansible/modules/apt_key.py +19 -12
- ansible/modules/apt_repository.py +19 -16
- ansible/modules/assemble.py +6 -6
- ansible/modules/assert.py +4 -4
- ansible/modules/async_status.py +10 -12
- ansible/modules/async_wrapper.py +8 -3
- ansible/modules/blockinfile.py +6 -7
- ansible/modules/command.py +10 -17
- ansible/modules/copy.py +57 -144
- ansible/modules/cron.py +20 -15
- ansible/modules/deb822_repository.py +8 -9
- ansible/modules/debconf.py +5 -5
- ansible/modules/debug.py +4 -4
- ansible/modules/dnf.py +8 -8
- ansible/modules/dnf5.py +39 -13
- ansible/modules/dpkg_selections.py +4 -4
- ansible/modules/expect.py +8 -10
- ansible/modules/fail.py +4 -4
- ansible/modules/fetch.py +4 -4
- ansible/modules/file.py +174 -133
- ansible/modules/find.py +19 -17
- ansible/modules/gather_facts.py +3 -3
- ansible/modules/get_url.py +59 -53
- ansible/modules/getent.py +7 -9
- ansible/modules/git.py +28 -25
- ansible/modules/group.py +6 -6
- ansible/modules/group_by.py +4 -4
- ansible/modules/hostname.py +13 -29
- ansible/modules/import_playbook.py +6 -6
- ansible/modules/import_role.py +6 -6
- ansible/modules/import_tasks.py +6 -6
- ansible/modules/include_role.py +6 -6
- ansible/modules/include_tasks.py +6 -6
- ansible/modules/include_vars.py +6 -6
- ansible/modules/iptables.py +86 -73
- ansible/modules/known_hosts.py +10 -10
- ansible/modules/lineinfile.py +5 -5
- ansible/modules/meta.py +4 -4
- ansible/modules/mount_facts.py +2 -2
- ansible/modules/package.py +4 -4
- ansible/modules/package_facts.py +22 -10
- ansible/modules/pause.py +6 -6
- ansible/modules/ping.py +6 -6
- ansible/modules/pip.py +10 -11
- ansible/modules/raw.py +4 -4
- ansible/modules/reboot.py +6 -6
- ansible/modules/replace.py +9 -13
- ansible/modules/rpm_key.py +7 -8
- ansible/modules/script.py +4 -4
- ansible/modules/service.py +7 -8
- ansible/modules/service_facts.py +87 -10
- ansible/modules/set_fact.py +5 -5
- ansible/modules/set_stats.py +4 -4
- ansible/modules/setup.py +2 -2
- ansible/modules/shell.py +6 -6
- ansible/modules/slurp.py +6 -6
- ansible/modules/stat.py +9 -23
- ansible/modules/subversion.py +15 -15
- ansible/modules/systemd.py +6 -6
- ansible/modules/systemd_service.py +6 -6
- ansible/modules/sysvinit.py +6 -6
- ansible/modules/tempfile.py +5 -6
- ansible/modules/template.py +6 -6
- ansible/modules/unarchive.py +32 -11
- ansible/modules/uri.py +33 -26
- ansible/modules/user.py +53 -34
- ansible/modules/validate_argument_spec.py +10 -7
- ansible/modules/wait_for.py +32 -27
- ansible/modules/wait_for_connection.py +6 -6
- ansible/modules/yum_repository.py +6 -6
- ansible/parsing/ajson.py +14 -32
- ansible/parsing/dataloader.py +99 -54
- ansible/parsing/mod_args.py +28 -44
- ansible/parsing/plugin_docs.py +21 -86
- ansible/parsing/quoting.py +1 -1
- ansible/parsing/splitter.py +27 -12
- ansible/parsing/utils/addresses.py +24 -24
- ansible/parsing/utils/jsonify.py +5 -1
- ansible/parsing/utils/yaml.py +32 -61
- ansible/parsing/vault/__init__.py +319 -87
- ansible/parsing/yaml/__init__.py +0 -18
- ansible/parsing/yaml/dumper.py +6 -120
- ansible/parsing/yaml/loader.py +6 -39
- ansible/parsing/yaml/objects.py +43 -335
- ansible/playbook/__init__.py +1 -1
- ansible/playbook/attribute.py +8 -3
- ansible/playbook/base.py +182 -132
- ansible/playbook/block.py +26 -24
- ansible/playbook/collectionsearch.py +1 -15
- ansible/playbook/conditional.py +3 -77
- ansible/playbook/handler.py +8 -2
- ansible/playbook/helpers.py +41 -53
- ansible/playbook/included_file.py +31 -27
- ansible/playbook/loop_control.py +2 -2
- ansible/playbook/play.py +85 -44
- ansible/playbook/play_context.py +12 -17
- ansible/playbook/playbook_include.py +14 -15
- ansible/playbook/role/__init__.py +24 -26
- ansible/playbook/role/definition.py +15 -17
- ansible/playbook/role/include.py +2 -4
- ansible/playbook/role/metadata.py +10 -11
- ansible/playbook/role_include.py +3 -3
- ansible/playbook/taggable.py +13 -8
- ansible/playbook/task.py +188 -118
- ansible/playbook/task_include.py +5 -5
- ansible/plugins/__init__.py +68 -21
- ansible/plugins/action/__init__.py +209 -176
- ansible/plugins/action/add_host.py +1 -1
- ansible/plugins/action/assemble.py +1 -1
- ansible/plugins/action/assert.py +54 -66
- ansible/plugins/action/copy.py +7 -11
- ansible/plugins/action/debug.py +37 -31
- ansible/plugins/action/dnf.py +3 -4
- ansible/plugins/action/fail.py +1 -1
- ansible/plugins/action/fetch.py +4 -5
- ansible/plugins/action/gather_facts.py +7 -6
- ansible/plugins/action/group_by.py +1 -1
- ansible/plugins/action/include_vars.py +10 -11
- ansible/plugins/action/package.py +3 -6
- ansible/plugins/action/pause.py +2 -2
- ansible/plugins/action/script.py +15 -8
- ansible/plugins/action/service.py +6 -11
- ansible/plugins/action/set_fact.py +3 -12
- ansible/plugins/action/set_stats.py +3 -8
- ansible/plugins/action/template.py +35 -59
- ansible/plugins/action/unarchive.py +1 -1
- ansible/plugins/action/validate_argument_spec.py +5 -5
- ansible/plugins/action/wait_for_connection.py +1 -1
- ansible/plugins/become/__init__.py +31 -8
- ansible/plugins/become/runas.py +71 -0
- ansible/plugins/become/su.py +13 -8
- ansible/plugins/become/sudo.py +19 -0
- ansible/plugins/cache/__init__.py +35 -44
- ansible/plugins/cache/base.py +8 -0
- ansible/plugins/cache/jsonfile.py +10 -16
- ansible/plugins/cache/memory.py +6 -12
- ansible/plugins/callback/__init__.py +284 -179
- ansible/plugins/callback/default.py +99 -92
- ansible/plugins/callback/junit.py +44 -39
- ansible/plugins/callback/minimal.py +28 -25
- ansible/plugins/callback/oneline.py +28 -21
- ansible/plugins/callback/tree.py +16 -11
- ansible/plugins/connection/__init__.py +47 -34
- ansible/plugins/connection/local.py +150 -54
- ansible/plugins/connection/paramiko_ssh.py +21 -18
- ansible/plugins/connection/psrp.py +76 -165
- ansible/plugins/connection/ssh.py +301 -78
- ansible/plugins/connection/winrm.py +58 -140
- ansible/plugins/doc_fragments/action_common_attributes.py +14 -14
- ansible/plugins/doc_fragments/action_core.py +6 -6
- ansible/plugins/doc_fragments/backup.py +2 -2
- ansible/plugins/doc_fragments/checksum_common.py +27 -0
- ansible/plugins/doc_fragments/constructed.py +6 -2
- ansible/plugins/doc_fragments/decrypt.py +2 -2
- ansible/plugins/doc_fragments/default_callback.py +2 -2
- ansible/plugins/doc_fragments/files.py +2 -2
- ansible/plugins/doc_fragments/inventory_cache.py +2 -2
- ansible/plugins/doc_fragments/result_format_callback.py +2 -2
- ansible/plugins/doc_fragments/return_common.py +2 -2
- ansible/plugins/doc_fragments/template_common.py +4 -4
- ansible/plugins/doc_fragments/url.py +17 -1
- ansible/plugins/doc_fragments/url_windows.py +2 -2
- ansible/plugins/doc_fragments/validate.py +2 -2
- ansible/plugins/doc_fragments/vars_plugin_staging.py +2 -2
- ansible/plugins/filter/__init__.py +6 -2
- ansible/plugins/filter/b64decode.yml +22 -0
- ansible/plugins/filter/b64encode.yml +22 -0
- ansible/plugins/filter/bool.yml +11 -4
- ansible/plugins/filter/core.py +225 -108
- ansible/plugins/filter/encryption.py +32 -32
- ansible/plugins/filter/flatten.yml +3 -2
- ansible/plugins/filter/human_to_bytes.yml +1 -1
- ansible/plugins/filter/mathstuff.py +30 -37
- ansible/plugins/filter/password_hash.yml +8 -0
- ansible/plugins/filter/regex_search.yml +1 -4
- ansible/plugins/filter/split.yml +1 -1
- ansible/plugins/filter/to_nice_yaml.yml +0 -4
- ansible/plugins/filter/to_yaml.yml +0 -4
- ansible/plugins/filter/unvault.yml +1 -1
- ansible/plugins/filter/urls.py +1 -1
- ansible/plugins/filter/urlsplit.py +8 -9
- ansible/plugins/filter/vault.yml +14 -9
- ansible/plugins/filter/win_basename.yml +6 -1
- ansible/plugins/filter/win_dirname.yml +5 -0
- ansible/plugins/inventory/__init__.py +97 -77
- ansible/plugins/inventory/advanced_host_list.py +7 -5
- ansible/plugins/inventory/auto.py +11 -4
- ansible/plugins/inventory/constructed.py +21 -24
- ansible/plugins/inventory/generator.py +16 -11
- ansible/plugins/inventory/host_list.py +7 -5
- ansible/plugins/inventory/ini.py +78 -44
- ansible/plugins/inventory/script.py +189 -119
- ansible/plugins/inventory/toml.py +16 -126
- ansible/plugins/inventory/yaml.py +10 -8
- ansible/plugins/list.py +3 -3
- ansible/plugins/loader.py +197 -82
- ansible/plugins/lookup/__init__.py +21 -4
- ansible/plugins/lookup/config.py +21 -35
- ansible/plugins/lookup/csvfile.py +3 -2
- ansible/plugins/lookup/dict.py +1 -6
- ansible/plugins/lookup/env.py +12 -9
- ansible/plugins/lookup/file.py +5 -8
- ansible/plugins/lookup/first_found.py +86 -55
- ansible/plugins/lookup/indexed_items.py +1 -10
- ansible/plugins/lookup/ini.py +14 -13
- ansible/plugins/lookup/items.py +1 -1
- ansible/plugins/lookup/lines.py +8 -1
- ansible/plugins/lookup/list.py +1 -1
- ansible/plugins/lookup/nested.py +2 -18
- ansible/plugins/lookup/password.py +5 -5
- ansible/plugins/lookup/pipe.py +5 -7
- ansible/plugins/lookup/sequence.py +18 -8
- ansible/plugins/lookup/subelements.py +1 -4
- ansible/plugins/lookup/template.py +42 -36
- ansible/plugins/lookup/together.py +0 -12
- ansible/plugins/lookup/unvault.py +1 -5
- ansible/plugins/lookup/url.py +2 -8
- ansible/plugins/lookup/vars.py +16 -24
- ansible/plugins/shell/__init__.py +2 -2
- ansible/plugins/shell/cmd.py +2 -2
- ansible/plugins/shell/powershell.py +39 -22
- ansible/plugins/shell/sh.py +3 -2
- ansible/plugins/strategy/__init__.py +159 -184
- ansible/plugins/strategy/debug.py +2 -2
- ansible/plugins/strategy/free.py +16 -31
- ansible/plugins/strategy/host_pinned.py +2 -2
- ansible/plugins/strategy/linear.py +41 -41
- ansible/plugins/terminal/__init__.py +4 -4
- ansible/plugins/test/__init__.py +7 -2
- ansible/plugins/test/core.py +55 -21
- ansible/plugins/test/files.py +1 -1
- ansible/plugins/test/mathstuff.py +3 -3
- ansible/plugins/test/uri.py +3 -3
- ansible/plugins/vars/host_group_vars.py +7 -14
- ansible/release.py +2 -2
- ansible/template/__init__.py +370 -944
- ansible/utils/__init__.py +0 -18
- ansible/utils/_ssh_agent.py +657 -0
- ansible/utils/collection_loader/__init__.py +52 -5
- ansible/utils/collection_loader/_collection_config.py +5 -6
- ansible/utils/collection_loader/_collection_finder.py +79 -93
- ansible/utils/collection_loader/_collection_meta.py +13 -8
- ansible/utils/display.py +433 -63
- ansible/utils/encrypt.py +27 -19
- ansible/utils/fqcn.py +2 -2
- ansible/utils/hashing.py +2 -2
- ansible/utils/helpers.py +2 -2
- ansible/utils/listify.py +8 -8
- ansible/utils/lock.py +2 -2
- ansible/utils/path.py +4 -4
- ansible/utils/plugin_docs.py +14 -13
- ansible/utils/sentinel.py +4 -62
- ansible/utils/singleton.py +2 -0
- ansible/utils/ssh_functions.py +1 -1
- ansible/utils/unsafe_proxy.py +23 -332
- ansible/utils/vars.py +51 -8
- ansible/utils/version.py +2 -2
- ansible/vars/clean.py +5 -5
- ansible/vars/hostvars.py +60 -90
- ansible/vars/manager.py +206 -282
- ansible/vars/reserved.py +8 -9
- ansible_core-2.19.0b2.dist-info/BSD-3-Clause.txt +28 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/METADATA +5 -4
- ansible_core-2.19.0b2.dist-info/RECORD +1072 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/WHEEL +1 -1
- ansible_test/_data/completion/docker.txt +7 -7
- ansible_test/_data/completion/remote.txt +6 -6
- ansible_test/_data/completion/windows.txt +1 -0
- ansible_test/_data/requirements/ansible.txt +2 -2
- ansible_test/_data/requirements/sanity.ansible-doc.txt +3 -3
- ansible_test/_data/requirements/sanity.changelog.txt +1 -1
- ansible_test/_data/requirements/sanity.import.plugin.txt +2 -2
- ansible_test/_data/requirements/sanity.pylint.txt +4 -4
- ansible_test/_data/requirements/sanity.validate-modules.txt +2 -2
- ansible_test/_data/requirements/sanity.yamllint.txt +1 -1
- ansible_test/_data/requirements/units.txt +1 -0
- ansible_test/_internal/__init__.py +1 -0
- ansible_test/_internal/ansible_util.py +2 -0
- ansible_test/_internal/become.py +1 -0
- ansible_test/_internal/bootstrap.py +1 -0
- ansible_test/_internal/cache.py +1 -0
- ansible_test/_internal/cgroup.py +1 -0
- ansible_test/_internal/ci/__init__.py +1 -0
- ansible_test/_internal/ci/azp.py +1 -0
- ansible_test/_internal/ci/local.py +1 -0
- ansible_test/_internal/classification/__init__.py +1 -0
- ansible_test/_internal/classification/common.py +1 -0
- ansible_test/_internal/classification/csharp.py +1 -0
- ansible_test/_internal/classification/powershell.py +1 -0
- ansible_test/_internal/classification/python.py +1 -0
- ansible_test/_internal/cli/__init__.py +1 -0
- ansible_test/_internal/cli/actions.py +1 -0
- ansible_test/_internal/cli/argparsing/__init__.py +1 -0
- ansible_test/_internal/cli/argparsing/actions.py +1 -0
- ansible_test/_internal/cli/argparsing/argcompletion.py +1 -0
- ansible_test/_internal/cli/argparsing/parsers.py +1 -0
- ansible_test/_internal/cli/commands/__init__.py +11 -0
- ansible_test/_internal/cli/commands/coverage/__init__.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/__init__.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/__init__.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/combine.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/expand.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/filter.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/generate.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/missing.py +1 -0
- ansible_test/_internal/cli/commands/coverage/combine.py +1 -0
- ansible_test/_internal/cli/commands/coverage/erase.py +1 -0
- ansible_test/_internal/cli/commands/coverage/html.py +1 -0
- ansible_test/_internal/cli/commands/coverage/report.py +1 -0
- ansible_test/_internal/cli/commands/coverage/xml.py +1 -0
- ansible_test/_internal/cli/commands/env.py +1 -0
- ansible_test/_internal/cli/commands/integration/__init__.py +1 -0
- ansible_test/_internal/cli/commands/integration/network.py +1 -0
- ansible_test/_internal/cli/commands/integration/posix.py +1 -0
- ansible_test/_internal/cli/commands/integration/windows.py +1 -0
- ansible_test/_internal/cli/commands/sanity.py +9 -0
- ansible_test/_internal/cli/commands/shell.py +1 -0
- ansible_test/_internal/cli/commands/units.py +1 -0
- ansible_test/_internal/cli/compat.py +1 -0
- ansible_test/_internal/cli/completers.py +1 -0
- ansible_test/_internal/cli/converters.py +1 -0
- ansible_test/_internal/cli/environments.py +1 -0
- ansible_test/_internal/cli/epilog.py +1 -0
- ansible_test/_internal/cli/parsers/__init__.py +1 -0
- ansible_test/_internal/cli/parsers/base_argument_parsers.py +1 -0
- ansible_test/_internal/cli/parsers/helpers.py +1 -0
- ansible_test/_internal/cli/parsers/host_config_parsers.py +1 -0
- ansible_test/_internal/cli/parsers/key_value_parsers.py +1 -0
- ansible_test/_internal/cli/parsers/value_parsers.py +1 -0
- ansible_test/_internal/commands/__init__.py +1 -0
- ansible_test/_internal/commands/coverage/__init__.py +2 -1
- ansible_test/_internal/commands/coverage/analyze/__init__.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/__init__.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/combine.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/expand.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/filter.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/generate.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/missing.py +1 -0
- ansible_test/_internal/commands/coverage/combine.py +2 -1
- ansible_test/_internal/commands/coverage/erase.py +1 -0
- ansible_test/_internal/commands/coverage/html.py +1 -0
- ansible_test/_internal/commands/coverage/report.py +1 -0
- ansible_test/_internal/commands/coverage/xml.py +1 -0
- ansible_test/_internal/commands/env/__init__.py +2 -0
- ansible_test/_internal/commands/integration/__init__.py +4 -0
- ansible_test/_internal/commands/integration/cloud/__init__.py +1 -0
- ansible_test/_internal/commands/integration/cloud/acme.py +2 -1
- ansible_test/_internal/commands/integration/cloud/aws.py +1 -0
- ansible_test/_internal/commands/integration/cloud/azure.py +1 -0
- ansible_test/_internal/commands/integration/cloud/cs.py +1 -0
- ansible_test/_internal/commands/integration/cloud/digitalocean.py +1 -0
- ansible_test/_internal/commands/integration/cloud/galaxy.py +3 -2
- ansible_test/_internal/commands/integration/cloud/hcloud.py +1 -0
- ansible_test/_internal/commands/integration/cloud/httptester.py +2 -1
- ansible_test/_internal/commands/integration/cloud/nios.py +2 -1
- ansible_test/_internal/commands/integration/cloud/opennebula.py +1 -0
- ansible_test/_internal/commands/integration/cloud/openshift.py +1 -0
- ansible_test/_internal/commands/integration/cloud/scaleway.py +1 -0
- ansible_test/_internal/commands/integration/cloud/vcenter.py +1 -0
- ansible_test/_internal/commands/integration/cloud/vultr.py +1 -0
- ansible_test/_internal/commands/integration/coverage.py +1 -0
- ansible_test/_internal/commands/integration/filters.py +1 -0
- ansible_test/_internal/commands/integration/network.py +1 -0
- ansible_test/_internal/commands/integration/posix.py +1 -0
- ansible_test/_internal/commands/integration/windows.py +1 -0
- ansible_test/_internal/commands/sanity/__init__.py +16 -1
- ansible_test/_internal/commands/sanity/ansible_doc.py +1 -0
- ansible_test/_internal/commands/sanity/bin_symlinks.py +1 -0
- ansible_test/_internal/commands/sanity/compile.py +1 -0
- ansible_test/_internal/commands/sanity/ignores.py +1 -0
- ansible_test/_internal/commands/sanity/import.py +1 -0
- ansible_test/_internal/commands/sanity/integration_aliases.py +1 -0
- ansible_test/_internal/commands/sanity/pep8.py +1 -0
- ansible_test/_internal/commands/sanity/pslint.py +1 -0
- ansible_test/_internal/commands/sanity/pylint.py +24 -26
- ansible_test/_internal/commands/sanity/shellcheck.py +1 -0
- ansible_test/_internal/commands/sanity/validate_modules.py +1 -0
- ansible_test/_internal/commands/sanity/yamllint.py +1 -0
- ansible_test/_internal/commands/shell/__init__.py +1 -0
- ansible_test/_internal/commands/units/__init__.py +1 -0
- ansible_test/_internal/compat/__init__.py +1 -0
- ansible_test/_internal/compat/packaging.py +1 -0
- ansible_test/_internal/compat/yaml.py +1 -0
- ansible_test/_internal/completion.py +1 -0
- ansible_test/_internal/config.py +2 -0
- ansible_test/_internal/connections.py +1 -0
- ansible_test/_internal/constants.py +1 -0
- ansible_test/_internal/containers.py +1 -0
- ansible_test/_internal/content_config.py +1 -0
- ansible_test/_internal/core_ci.py +1 -0
- ansible_test/_internal/coverage_util.py +11 -10
- ansible_test/_internal/data.py +1 -0
- ansible_test/_internal/delegation.py +1 -0
- ansible_test/_internal/dev/__init__.py +1 -0
- ansible_test/_internal/dev/container_probe.py +1 -0
- ansible_test/_internal/diff.py +3 -2
- ansible_test/_internal/docker_util.py +2 -1
- ansible_test/_internal/encoding.py +1 -0
- ansible_test/_internal/executor.py +1 -0
- ansible_test/_internal/git.py +1 -0
- ansible_test/_internal/host_configs.py +1 -0
- ansible_test/_internal/host_profiles.py +1 -0
- ansible_test/_internal/http.py +1 -0
- ansible_test/_internal/init.py +1 -0
- ansible_test/_internal/inventory.py +35 -3
- ansible_test/_internal/io.py +1 -0
- ansible_test/_internal/metadata.py +1 -0
- ansible_test/_internal/payload.py +1 -0
- ansible_test/_internal/provider/__init__.py +1 -0
- ansible_test/_internal/provider/layout/__init__.py +1 -0
- ansible_test/_internal/provider/layout/ansible.py +1 -0
- ansible_test/_internal/provider/layout/collection.py +1 -0
- ansible_test/_internal/provider/layout/unsupported.py +1 -0
- ansible_test/_internal/provider/source/__init__.py +1 -0
- ansible_test/_internal/provider/source/git.py +1 -0
- ansible_test/_internal/provider/source/installed.py +1 -0
- ansible_test/_internal/provider/source/unsupported.py +1 -0
- ansible_test/_internal/provider/source/unversioned.py +1 -0
- ansible_test/_internal/provisioning.py +1 -0
- ansible_test/_internal/pypi_proxy.py +6 -5
- ansible_test/_internal/python_requirements.py +1 -0
- ansible_test/_internal/ssh.py +1 -0
- ansible_test/_internal/target.py +1 -0
- ansible_test/_internal/test.py +3 -2
- ansible_test/_internal/thread.py +1 -0
- ansible_test/_internal/timeout.py +1 -0
- ansible_test/_internal/util.py +1 -0
- ansible_test/_internal/util_common.py +5 -2
- ansible_test/_internal/venv.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/action-plugin-docs.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/changelog/sphinx.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/changelog.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/empty-init.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/line-endings.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-assert.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-get-exception.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-illegal-filenames.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-smart-quotes.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/replace-urlopen.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/runtime-metadata.py +28 -1
- ansible_test/_util/controller/sanity/code-smell/shebang.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/symlinks.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/use-argspec-type-path.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/use-compat-six.py +1 -0
- ansible_test/_util/controller/sanity/integration-aliases/yaml_to_json.py +2 -1
- ansible_test/_util/controller/sanity/pep8/current-ignore.txt +4 -0
- ansible_test/_util/controller/sanity/pylint/config/ansible-test-target.cfg +7 -5
- ansible_test/_util/controller/sanity/pylint/config/ansible-test.cfg +7 -5
- ansible_test/_util/controller/sanity/pylint/config/code-smell.cfg +7 -5
- ansible_test/_util/controller/sanity/pylint/config/collection.cfg +3 -5
- ansible_test/_util/controller/sanity/pylint/config/default.cfg +7 -7
- ansible_test/_util/controller/sanity/pylint/plugins/deprecated.py +1 -13
- ansible_test/_util/controller/sanity/pylint/plugins/hide_unraisable.py +1 -0
- ansible_test/_util/controller/sanity/pylint/plugins/string_format.py +1 -8
- ansible_test/_util/controller/sanity/pylint/plugins/unwanted.py +1 -8
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py +55 -28
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/module_args.py +12 -5
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/schema.py +13 -2
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/utils.py +1 -0
- ansible_test/_util/controller/sanity/yamllint/yamllinter.py +35 -17
- ansible_test/_util/controller/tools/collection_detail.py +1 -0
- ansible_test/_util/controller/tools/yaml_to_json.py +2 -1
- ansible_test/_util/target/pytest/plugins/ansible_forked.py +6 -1
- ansible_test/_util/target/pytest/plugins/ansible_pytest_collections.py +2 -1
- ansible_test/_util/target/pytest/plugins/ansible_pytest_coverage.py +1 -0
- ansible_test/_util/target/sanity/compile/compile.py +1 -0
- ansible_test/_util/target/sanity/import/importer.py +15 -16
- ansible_test/_util/target/setup/bootstrap.sh +9 -20
- ansible_test/_util/target/setup/probe_cgroups.py +1 -0
- ansible_test/_util/target/setup/quiet_pip.py +1 -0
- ansible_test/_util/target/setup/requirements.py +35 -27
- ansible_test/_util/target/tools/virtualenvcheck.py +2 -1
- ansible_test/_util/target/tools/yamlcheck.py +2 -1
- ansible/compat/selectors.py +0 -32
- ansible/errors/yaml_strings.py +0 -138
- ansible/executor/action_write_locks.py +0 -44
- ansible/executor/discovery/python_target.py +0 -47
- ansible/executor/powershell/module_powershell_wrapper.ps1 +0 -86
- ansible/executor/powershell/module_script_wrapper.ps1 +0 -22
- ansible/module_utils/compat/importlib.py +0 -26
- ansible/module_utils/compat/selectors.py +0 -32
- ansible/module_utils/pycompat24.py +0 -73
- ansible/parsing/yaml/constructor.py +0 -178
- ansible/template/native_helpers.py +0 -251
- ansible/template/template.py +0 -43
- ansible/template/vars.py +0 -77
- ansible/utils/native_jinja.py +0 -11
- ansible/vars/fact_cache.py +0 -71
- ansible_core-2.18.5rc1.dist-info/RECORD +0 -992
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/Apache-License.txt +0 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/COPYING +0 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/MIT-license.txt +0 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/PSF-license.txt +0 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/entry_points.txt +0 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/simplified_bsd.txt +0 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/top_level.txt +0 -0
@@ -4,38 +4,61 @@
|
|
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
|
+
|
34
|
+
|
35
|
+
@dataclasses.dataclass(frozen=True, kw_only=True)
|
36
|
+
class _ScriptInfo:
|
37
|
+
content: dataclasses.InitVar[bytes]
|
38
|
+
path: str
|
39
|
+
script: str = dataclasses.field(init=False)
|
40
|
+
|
41
|
+
def __post_init__(self, content: bytes) -> None:
|
42
|
+
object.__setattr__(self, 'script', base64.b64encode(content).decode())
|
43
|
+
|
44
|
+
|
45
|
+
@dataclasses.dataclass(frozen=True, kw_only=True)
|
46
|
+
class _ManifestAction:
|
47
|
+
name: str
|
48
|
+
params: dict[str, object] = dataclasses.field(default_factory=dict)
|
49
|
+
secure_params: dict[str, object] = dataclasses.field(default_factory=dict)
|
22
50
|
|
23
51
|
|
24
52
|
class PSModuleDepFinder(object):
|
25
53
|
|
26
|
-
def __init__(self):
|
54
|
+
def __init__(self) -> None:
|
27
55
|
# This is also used by validate-modules to get a module's required utils in base and a collection.
|
28
|
-
self.
|
29
|
-
self.exec_scripts = dict()
|
56
|
+
self.scripts: dict[str, _ScriptInfo] = {}
|
30
57
|
|
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()
|
58
|
+
self._util_deps: dict[str, set[str]] = {}
|
36
59
|
|
37
|
-
self.ps_version = None
|
38
|
-
self.os_version = None
|
60
|
+
self.ps_version: str | None = None
|
61
|
+
self.os_version: str | None = None
|
39
62
|
self.become = False
|
40
63
|
|
41
64
|
self._re_cs_module = [
|
@@ -70,36 +93,49 @@ class PSModuleDepFinder(object):
|
|
70
93
|
r'(\.[\w\.]+))(?P<optional>\s+-Optional){0,1}')),
|
71
94
|
]
|
72
95
|
|
73
|
-
self._re_wrapper = re.compile(to_bytes(r'(?i)^#\s*ansiblerequires\s+-wrapper\s+(\w*)'))
|
74
96
|
self._re_ps_version = re.compile(to_bytes(r'(?i)^#requires\s+\-version\s+([0-9]+(\.[0-9]+){0,3})$'))
|
75
97
|
self._re_os_version = re.compile(to_bytes(r'(?i)^#ansiblerequires\s+\-osversion\s+([0-9]+(\.[0-9]+){0,3})$'))
|
76
98
|
self._re_become = re.compile(to_bytes(r'(?i)^#ansiblerequires\s+\-become$'))
|
77
99
|
|
78
|
-
def
|
100
|
+
def scan_exec_script(self, name: str) -> None:
|
101
|
+
# scans lib/ansible/executor/powershell for scripts used in the module
|
102
|
+
# exec side. It also scans these scripts for any dependencies
|
103
|
+
if name in self.scripts:
|
104
|
+
return
|
105
|
+
|
106
|
+
exec_code = _get_powershell_script(name)
|
107
|
+
self.scripts[name] = _ScriptInfo(
|
108
|
+
content=exec_code,
|
109
|
+
path=name,
|
110
|
+
)
|
111
|
+
self.scan_module(exec_code, powershell=True)
|
112
|
+
|
113
|
+
def scan_module(
|
114
|
+
self,
|
115
|
+
module_data: bytes,
|
116
|
+
fqn: str | None = None,
|
117
|
+
powershell: bool = True,
|
118
|
+
) -> set[str]:
|
79
119
|
lines = module_data.split(b'\n')
|
80
|
-
module_utils = set()
|
81
|
-
if wrapper:
|
82
|
-
cs_utils = self.cs_utils_wrapper
|
83
|
-
else:
|
84
|
-
cs_utils = self.cs_utils_module
|
120
|
+
module_utils: set[tuple[str, str, bool]] = set()
|
85
121
|
|
86
122
|
if powershell:
|
87
123
|
checks = [
|
88
124
|
# PS module contains '#Requires -Module Ansible.ModuleUtils.*'
|
89
125
|
# PS module contains '#AnsibleRequires -Powershell Ansible.*' (or collections module_utils ref)
|
90
|
-
(self._re_ps_module,
|
126
|
+
(self._re_ps_module, ".psm1"),
|
91
127
|
# PS module contains '#AnsibleRequires -CSharpUtil Ansible.*' (or collections module_utils ref)
|
92
|
-
(self._re_cs_in_ps_module,
|
128
|
+
(self._re_cs_in_ps_module, ".cs"),
|
93
129
|
]
|
94
130
|
else:
|
95
131
|
checks = [
|
96
132
|
# CS module contains 'using Ansible.*;' or 'using ansible_collections.ns.coll.plugins.module_utils.*;'
|
97
|
-
(self._re_cs_module,
|
133
|
+
(self._re_cs_module, ".cs"),
|
98
134
|
]
|
99
135
|
|
100
136
|
for line in lines:
|
101
|
-
for
|
102
|
-
for pattern in
|
137
|
+
for patterns, util_extension in checks:
|
138
|
+
for pattern in patterns:
|
103
139
|
match = pattern.match(line)
|
104
140
|
if match:
|
105
141
|
# tolerate windows line endings by stripping any remaining
|
@@ -107,82 +143,66 @@ class PSModuleDepFinder(object):
|
|
107
143
|
module_util_name = to_text(match.group(1).rstrip())
|
108
144
|
match_dict = match.groupdict()
|
109
145
|
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
|
-
|
146
|
+
module_utils.add((module_util_name, util_extension, optional))
|
114
147
|
break
|
115
148
|
|
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:
|
149
|
+
if not powershell:
|
150
|
+
continue
|
151
|
+
|
152
|
+
if ps_version_match := self._re_ps_version.match(line):
|
153
|
+
self._parse_version_match(ps_version_match, "ps_version")
|
154
|
+
|
155
|
+
if os_version_match := self._re_os_version.match(line):
|
156
|
+
self._parse_version_match(os_version_match, "os_version")
|
157
|
+
|
158
|
+
# once become is set, no need to keep on checking recursively
|
159
|
+
if not self.become and self._re_become.match(line):
|
160
|
+
self.become = True
|
161
|
+
|
162
|
+
dependencies: set[str] = set()
|
163
|
+
for name, ext, optional in set(module_utils):
|
164
|
+
util_name = self._scan_module_util(name, ext, fqn, optional)
|
165
|
+
if util_name:
|
166
|
+
dependencies.add(util_name)
|
167
|
+
util_deps = self._util_deps[util_name]
|
168
|
+
dependencies.update(util_deps)
|
169
|
+
|
170
|
+
return dependencies
|
171
|
+
|
172
|
+
def _scan_module_util(
|
173
|
+
self,
|
174
|
+
name: str,
|
175
|
+
ext: str,
|
176
|
+
module_fqn: str | None,
|
177
|
+
optional: bool,
|
178
|
+
) -> str | None:
|
179
|
+
util_name: str
|
180
|
+
util_path: str
|
181
|
+
util_data: bytes
|
182
|
+
util_fqn: str | None = None
|
183
|
+
|
184
|
+
if name.startswith("Ansible."):
|
185
|
+
# Builtin util, or the old role module_utils reference.
|
186
|
+
util_name = f"{name}{ext}"
|
187
|
+
|
188
|
+
if util_name in self._util_deps:
|
189
|
+
return util_name
|
190
|
+
|
191
|
+
util_path = ps_module_utils_loader.find_plugin(name, ext)
|
192
|
+
if not util_path or not os.path.exists(util_path):
|
173
193
|
if optional:
|
174
|
-
return
|
194
|
+
return None
|
195
|
+
|
196
|
+
raise AnsibleError(f"Could not find imported module util '{name}'")
|
175
197
|
|
176
|
-
|
177
|
-
|
198
|
+
with open(util_path, 'rb') as mu_file:
|
199
|
+
util_data = mu_file.read()
|
178
200
|
|
179
|
-
module_util_data = to_bytes(_slurp(mu_path))
|
180
201
|
else:
|
181
202
|
# Collection util, load the package data based on the util import.
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
fqn_submodules = fqn.split('.')
|
203
|
+
submodules = name.split(".")
|
204
|
+
if name.startswith('.'):
|
205
|
+
fqn_submodules = (module_fqn or "").split('.')
|
186
206
|
for submodule in submodules:
|
187
207
|
if submodule:
|
188
208
|
break
|
@@ -190,56 +210,70 @@ class PSModuleDepFinder(object):
|
|
190
210
|
|
191
211
|
submodules = fqn_submodules + [s for s in submodules if s]
|
192
212
|
|
193
|
-
|
194
|
-
|
213
|
+
util_package = '.'.join(submodules[:-1])
|
214
|
+
util_resource_name = f"{submodules[-1]}{ext}"
|
215
|
+
util_fqn = f"{util_package}.{submodules[-1]}"
|
216
|
+
util_name = f"{util_package}.{util_resource_name}"
|
217
|
+
|
218
|
+
if util_name in self._util_deps:
|
219
|
+
return util_name
|
195
220
|
|
196
221
|
try:
|
197
|
-
module_util = import_module(
|
198
|
-
|
199
|
-
if
|
222
|
+
module_util = import_module(util_package)
|
223
|
+
util_code = pkgutil.get_data(util_package, util_resource_name)
|
224
|
+
if util_code is None:
|
200
225
|
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')
|
226
|
+
util_data = util_code
|
204
227
|
|
205
228
|
# Get the path of the util which is required for coverage collection.
|
206
229
|
resource_paths = list(module_util.__path__)
|
207
230
|
if len(resource_paths) != 1:
|
208
231
|
# 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
|
-
|
232
|
+
raise AnsibleError(f"Internal error: Referenced module_util package '{util_package}' contains 0 "
|
233
|
+
"or multiple import locations when we only expect 1.")
|
234
|
+
|
235
|
+
util_path = os.path.join(resource_paths[0], util_resource_name)
|
212
236
|
except (ImportError, OSError) as err:
|
213
237
|
if getattr(err, "errno", errno.ENOENT) == errno.ENOENT:
|
214
238
|
if optional:
|
215
|
-
return
|
239
|
+
return None
|
216
240
|
|
217
|
-
raise AnsibleError(
|
218
|
-
% to_native(m))
|
241
|
+
raise AnsibleError(f"Could not find collection imported module support code for '{name}'")
|
219
242
|
|
220
243
|
else:
|
221
244
|
raise
|
222
245
|
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
self.scan_module(
|
246
|
+
# This is important to be set before scan_module is called to avoid
|
247
|
+
# recursive dependencies.
|
248
|
+
self.scripts[util_name] = _ScriptInfo(
|
249
|
+
content=util_data,
|
250
|
+
path=util_path,
|
251
|
+
)
|
252
|
+
|
253
|
+
# It is important this is set before calling scan_module to ensure
|
254
|
+
# recursive dependencies don't result in an infinite loop.
|
255
|
+
dependencies = self._util_deps[util_name] = set()
|
256
|
+
|
257
|
+
util_deps = self.scan_module(util_data, fqn=util_fqn, powershell=(ext == ".psm1"))
|
258
|
+
dependencies.update(util_deps)
|
259
|
+
for dep in dependencies:
|
260
|
+
if dep_list := self._util_deps.get(dep):
|
261
|
+
dependencies.update(dep_list)
|
262
|
+
|
263
|
+
if ext == ".cs":
|
264
|
+
# Any C# code requires the AddType.psm1 module to load.
|
265
|
+
dependencies.add("Ansible.ModuleUtils.AddType.psm1")
|
266
|
+
self._scan_module_util("Ansible.ModuleUtils.AddType", ".psm1", None, False)
|
267
|
+
|
268
|
+
return util_name
|
235
269
|
|
236
|
-
def _parse_version_match(self, match, attribute):
|
270
|
+
def _parse_version_match(self, match: re.Match, attribute: str) -> None:
|
237
271
|
new_version = to_text(match.group(1)).rstrip()
|
238
272
|
|
239
273
|
# PowerShell cannot cast a string of "1" to Version, it must have at
|
240
274
|
# least the major.minor for it to be valid so we append 0
|
241
275
|
if match.group(2) is None:
|
242
|
-
new_version = "
|
276
|
+
new_version = f"{new_version}.0"
|
243
277
|
|
244
278
|
existing_version = getattr(self, attribute, None)
|
245
279
|
if existing_version is None:
|
@@ -250,152 +284,270 @@ class PSModuleDepFinder(object):
|
|
250
284
|
setattr(self, attribute, new_version)
|
251
285
|
|
252
286
|
|
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
|
-
|
287
|
+
def _bootstrap_powershell_script(
|
288
|
+
name: str,
|
289
|
+
parameters: dict[str, t.Any] | None = None,
|
290
|
+
*,
|
291
|
+
has_input: bool = False,
|
292
|
+
) -> tuple[str, bytes]:
|
293
|
+
"""Build bootstrap wrapper for specified script.
|
294
|
+
|
295
|
+
Builds the bootstrap wrapper and input needed to run the specified executor
|
296
|
+
PowerShell script specified.
|
297
|
+
|
298
|
+
:param name: The name of the PowerShell script to run.
|
299
|
+
:param parameters: The parameters to pass to the script.
|
300
|
+
:param has_input: The script will be provided with input data.
|
301
|
+
:return: The bootstrap wrapper and input to provide to it.
|
302
|
+
"""
|
303
|
+
exec_manifest = _ExecManifest()
|
304
|
+
|
305
|
+
script = _get_powershell_script(name)
|
306
|
+
exec_manifest.scripts[name] = _ScriptInfo(
|
307
|
+
content=script,
|
308
|
+
path=name,
|
309
|
+
)
|
310
|
+
|
311
|
+
exec_manifest.actions.append(
|
312
|
+
_ManifestAction(
|
313
|
+
name=name,
|
314
|
+
params=parameters or {},
|
315
|
+
)
|
316
|
+
)
|
317
|
+
|
318
|
+
bootstrap_wrapper = _get_powershell_script("bootstrap_wrapper.ps1")
|
319
|
+
bootstrap_input = _get_bootstrap_input(exec_manifest)
|
320
|
+
if has_input:
|
321
|
+
bootstrap_input += b"\n\0\0\0\0\n"
|
322
|
+
|
323
|
+
return bootstrap_wrapper.decode(), bootstrap_input
|
324
|
+
|
325
|
+
|
326
|
+
def _get_powershell_script(
|
327
|
+
name: str,
|
328
|
+
) -> bytes:
|
329
|
+
"""Get the requested PowerShell script.
|
330
|
+
|
331
|
+
Gets the script stored in the ansible.executore.powershell package.
|
332
|
+
|
333
|
+
:param name: The name of the PowerShell script to retrieve.
|
334
|
+
:return: The contents of the requested PowerShell script as a byte string.
|
335
|
+
"""
|
336
|
+
package_name = 'ansible.executor.powershell'
|
337
|
+
|
338
|
+
code = pkgutil.get_data(package_name, name)
|
339
|
+
if code is None:
|
340
|
+
raise AnsibleFileNotFound(f"Could not find powershell script '{package_name}.{name}'")
|
341
|
+
|
342
|
+
return code
|
343
|
+
|
344
|
+
|
345
|
+
def _create_powershell_wrapper(
|
346
|
+
*,
|
347
|
+
name: str,
|
348
|
+
module_data: bytes,
|
349
|
+
module_path: str,
|
350
|
+
module_args: dict[t.Any, t.Any],
|
351
|
+
environment: dict[str, str],
|
352
|
+
async_timeout: int,
|
353
|
+
become_plugin: BecomeBase | None,
|
354
|
+
substyle: t.Literal["powershell", "script"],
|
355
|
+
task_vars: dict[str, t.Any],
|
356
|
+
profile: str,
|
357
|
+
) -> bytes:
|
358
|
+
"""Creates module or script wrapper for PowerShell.
|
359
|
+
|
360
|
+
Creates the input data to provide to bootstrap_wrapper.ps1 when running a
|
361
|
+
PowerShell module or script.
|
362
|
+
|
363
|
+
:param name: The fully qualified name of the module or script filename (without extension).
|
364
|
+
:param module_data: The data of the module or script.
|
365
|
+
:param module_path: The path of the module or script.
|
366
|
+
:param module_args: The arguments to pass to the module or script.
|
367
|
+
:param environment: The environment variables to set when running the module or script.
|
368
|
+
:param async_timeout: The timeout to use for async execution or 0 for no async.
|
369
|
+
:param become_plugin: The become plugin to use for privilege escalation or None for no become.
|
370
|
+
:param substyle: The substyle of the module or script to run [powershell or script].
|
371
|
+
:param task_vars: The task variables used on the task.
|
372
|
+
|
373
|
+
:return: The input data for bootstrap_wrapper.ps1 as a byte string.
|
374
|
+
"""
|
375
|
+
|
376
|
+
actions: list[_ManifestAction] = []
|
295
377
|
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,
|
378
|
+
finder.scan_exec_script('module_wrapper.ps1')
|
379
|
+
|
380
|
+
ext = os.path.splitext(module_path)[1]
|
381
|
+
name_with_ext = f"{name}{ext}"
|
382
|
+
finder.scripts[name_with_ext] = _ScriptInfo(
|
383
|
+
content=module_data,
|
384
|
+
path=module_path,
|
311
385
|
)
|
312
|
-
|
386
|
+
|
387
|
+
module_params: dict[str, t.Any] = {
|
388
|
+
'Script': name_with_ext,
|
389
|
+
'Environment': environment,
|
390
|
+
}
|
391
|
+
if substyle != 'script':
|
392
|
+
module_deps = finder.scan_module(
|
393
|
+
module_data,
|
394
|
+
fqn=name,
|
395
|
+
powershell=True,
|
396
|
+
)
|
397
|
+
cs_deps = []
|
398
|
+
ps_deps = []
|
399
|
+
for dep in module_deps:
|
400
|
+
if dep.endswith('.cs'):
|
401
|
+
cs_deps.append(dep)
|
402
|
+
else:
|
403
|
+
ps_deps.append(dep)
|
404
|
+
|
405
|
+
module_params |= {
|
406
|
+
'Variables': [
|
407
|
+
{
|
408
|
+
'Name': 'complex_args',
|
409
|
+
'Value': _prepare_module_args(module_args, profile),
|
410
|
+
'Scope': 'Global',
|
411
|
+
},
|
412
|
+
],
|
413
|
+
'CSharpModules': cs_deps,
|
414
|
+
'PowerShellModules': ps_deps,
|
415
|
+
'ForModule': True,
|
416
|
+
}
|
417
|
+
|
418
|
+
if become_plugin or finder.become:
|
419
|
+
become_script = 'become_wrapper.ps1'
|
420
|
+
become_params: dict[str, t.Any] = {
|
421
|
+
'BecomeUser': 'SYSTEM',
|
422
|
+
}
|
423
|
+
become_secure_params: dict[str, t.Any] = {}
|
424
|
+
|
425
|
+
if become_plugin:
|
426
|
+
if not isinstance(become_plugin, RunasBecomeModule):
|
427
|
+
msg = f"Become plugin {become_plugin.name} is not supported by the Windows exec wrapper. Make sure to set the become method to runas."
|
428
|
+
raise AnsibleError(msg)
|
429
|
+
|
430
|
+
become_script, become_params, become_secure_params = become_plugin._build_powershell_wrapper_action()
|
431
|
+
|
432
|
+
finder.scan_exec_script('exec_wrapper.ps1')
|
433
|
+
finder.scan_exec_script(become_script)
|
434
|
+
actions.append(
|
435
|
+
_ManifestAction(
|
436
|
+
name=become_script,
|
437
|
+
params=become_params,
|
438
|
+
secure_params=become_secure_params,
|
439
|
+
)
|
440
|
+
)
|
313
441
|
|
314
442
|
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
|
-
)
|
443
|
+
finder.scan_exec_script('bootstrap_wrapper.ps1')
|
444
|
+
finder.scan_exec_script('exec_wrapper.ps1')
|
445
|
+
|
446
|
+
async_dir = environment.get('ANSIBLE_ASYNC_DIR', None)
|
447
|
+
if not async_dir:
|
448
|
+
raise AnsibleError("The environment variable 'ANSIBLE_ASYNC_DIR' is not set.")
|
449
|
+
|
450
|
+
finder.scan_exec_script('async_wrapper.ps1')
|
451
|
+
actions.append(
|
452
|
+
_ManifestAction(
|
453
|
+
name='async_wrapper.ps1',
|
454
|
+
params={
|
455
|
+
'AsyncDir': async_dir,
|
456
|
+
'AsyncJid': f'j{secrets.randbelow(999999999999)}',
|
457
|
+
'StartupTimeout': C.config.get_config_value("WIN_ASYNC_STARTUP_TIMEOUT", variables=task_vars),
|
458
|
+
},
|
459
|
+
)
|
460
|
+
)
|
461
|
+
|
462
|
+
finder.scan_exec_script('async_watchdog.ps1')
|
463
|
+
actions.append(
|
464
|
+
_ManifestAction(
|
465
|
+
name='async_watchdog.ps1',
|
466
|
+
params={
|
467
|
+
'Timeout': async_timeout,
|
468
|
+
},
|
469
|
+
)
|
470
|
+
)
|
471
|
+
|
350
472
|
coverage_output = C.config.get_config_value('COVERAGE_REMOTE_OUTPUT', variables=task_vars)
|
351
473
|
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
|
-
|
474
|
+
path_filter = C.config.get_config_value('COVERAGE_REMOTE_PATHS', variables=task_vars)
|
475
|
+
|
476
|
+
finder.scan_exec_script('coverage_wrapper.ps1')
|
477
|
+
actions.append(
|
478
|
+
_ManifestAction(
|
479
|
+
name='coverage_wrapper.ps1',
|
480
|
+
params={
|
481
|
+
'ModuleName': name_with_ext,
|
482
|
+
'OutputPath': coverage_output,
|
483
|
+
'PathFilter': path_filter,
|
484
|
+
},
|
485
|
+
)
|
486
|
+
)
|
487
|
+
|
488
|
+
actions.append(
|
489
|
+
_ManifestAction(
|
490
|
+
name='module_wrapper.ps1',
|
491
|
+
params=module_params,
|
492
|
+
),
|
493
|
+
)
|
494
|
+
|
495
|
+
temp_path: str | None = None
|
496
|
+
for temp_key in ['_ansible_tmpdir', '_ansible_remote_tmp']:
|
497
|
+
if temp_value := module_args.get(temp_key, None):
|
498
|
+
temp_path = temp_value
|
499
|
+
break
|
500
|
+
|
501
|
+
exec_manifest = _ExecManifest(
|
502
|
+
scripts=finder.scripts,
|
503
|
+
actions=actions,
|
504
|
+
)
|
505
|
+
|
506
|
+
return _get_bootstrap_input(
|
507
|
+
exec_manifest,
|
508
|
+
min_os_version=finder.os_version,
|
509
|
+
min_ps_version=finder.ps_version,
|
510
|
+
temp_path=temp_path,
|
511
|
+
)
|
512
|
+
|
513
|
+
|
514
|
+
def _get_bootstrap_input(
|
515
|
+
manifest: _ExecManifest,
|
516
|
+
min_os_version: str | None = None,
|
517
|
+
min_ps_version: str | None = None,
|
518
|
+
temp_path: str | None = None,
|
519
|
+
) -> bytes:
|
520
|
+
"""Gets the input for bootstrap_wrapper.ps1
|
521
|
+
|
522
|
+
Gets the input needed to send to bootstrap_wrapper.ps1 to run code through
|
523
|
+
exec_wrapper.ps1.
|
524
|
+
|
525
|
+
:param manifest: The exec wrapper manifest of scripts and actions to run.
|
526
|
+
:param min_os_version: The minimum OS version required to run the scripts.
|
527
|
+
:param min_ps_version: The minimum PowerShell version required to run the scripts.
|
528
|
+
:param temp_path: The temporary path to use for the scripts if needed.
|
529
|
+
:return: The input for bootstrap_wrapper.ps1 as a byte string.
|
530
|
+
"""
|
531
|
+
bootstrap_manifest = {
|
532
|
+
'name': 'exec_wrapper',
|
533
|
+
'script': _get_powershell_script("exec_wrapper.ps1").decode(),
|
534
|
+
'params': {
|
535
|
+
'MinOSVersion': min_os_version,
|
536
|
+
'MinPSVersion': min_ps_version,
|
537
|
+
'TempPath': temp_path,
|
538
|
+
},
|
539
|
+
}
|
540
|
+
|
541
|
+
bootstrap_input = json.dumps(bootstrap_manifest, ensure_ascii=True)
|
542
|
+
exec_input = json.dumps(dataclasses.asdict(manifest))
|
543
|
+
return f"{bootstrap_input}\n\0\0\0\0\n{exec_input}".encode()
|
544
|
+
|
545
|
+
|
546
|
+
def _prepare_module_args(module_args: dict[str, t.Any], profile: str) -> dict[str, t.Any]:
|
547
|
+
"""
|
548
|
+
Serialize the module args with the specified profile and deserialize them with the Python built-in JSON decoder.
|
549
|
+
This is used to facilitate serializing module args with a different encoder (profile) than is used for the manifest.
|
550
|
+
"""
|
551
|
+
encoder = get_module_encoder(profile, Direction.CONTROLLER_TO_MODULE)
|
552
|
+
|
553
|
+
return json.loads(json.dumps(module_args, cls=encoder))
|