├── tests ├── unit │ ├── __init__.py │ ├── plugins │ │ ├── __init__.py │ │ ├── action │ │ │ ├── __init__.py │ │ │ └── test_win_copy.py │ │ └── filter │ │ │ └── __init__.py │ ├── test_data │ │ └── win_updates │ │ │ ├── fail_poll_script.txt │ │ │ ├── fail_poll_script_critical_stdout.txt │ │ │ └── install_reboot_two_failures.txt │ ├── requirements.txt │ └── conftest.py ├── .gitignore ├── integration │ └── targets │ │ ├── __init__.py │ │ ├── win_copy │ │ ├── files │ │ │ ├── empty.txt │ │ │ ├── foo.txt │ │ │ └── subdir │ │ │ │ ├── bar.txt │ │ │ │ └── subdir2 │ │ │ │ ├── baz.txt │ │ │ │ └── subdir3 │ │ │ │ └── subdir4 │ │ │ │ └── qux.txt │ │ ├── aliases │ │ ├── defaults │ │ │ └── main.yml │ │ ├── files-different │ │ │ └── vault │ │ │ │ ├── readme.txt │ │ │ │ ├── vault-file │ │ │ │ └── folder │ │ │ │ └── nested-vault-file │ │ └── tasks │ │ │ └── main.yml │ │ ├── win_file │ │ ├── files │ │ │ ├── foobar │ │ │ │ ├── fileB │ │ │ │ ├── directory │ │ │ │ │ ├── fileC │ │ │ │ │ └── fileD │ │ │ │ └── fileA │ │ │ └── foo.txt │ │ ├── aliases │ │ └── meta │ │ │ └── main.yml │ │ ├── win_setup │ │ ├── files │ │ │ ├── false_fact.ps1 │ │ │ ├── true_fact.ps1 │ │ │ ├── other_facts.ps1 │ │ │ ├── will_skip.txt │ │ │ ├── my_facts.ps1 │ │ │ └── json_facts.json │ │ ├── aliases │ │ └── meta │ │ │ └── main.yml │ │ ├── win_acl │ │ ├── aliases │ │ ├── meta │ │ │ └── main.yml │ │ ├── defaults │ │ │ └── main.yml │ │ └── tasks │ │ │ └── main.yml │ │ ├── win_async │ │ ├── aliases │ │ └── tasks │ │ │ └── main.yml │ │ ├── win_dsc │ │ ├── aliases │ │ ├── meta │ │ │ └── main.yml │ │ ├── files │ │ │ ├── xTestDsc │ │ │ │ ├── 1.0.0 │ │ │ │ │ ├── DSCResources │ │ │ │ │ │ └── ANSIBLE_xSetReboot │ │ │ │ │ │ │ ├── ANSIBLE_xSetReboot.schema.mof │ │ │ │ │ │ │ └── ANSIBLE_xSetReboot.psm1 │ │ │ │ │ └── xTestDsc.psd1 │ │ │ │ └── 1.0.1 │ │ │ │ │ └── xTestDsc.psd1 │ │ │ ├── xTestCompositeDsc │ │ │ │ └── 1.0.0 │ │ │ │ │ ├── DSCResources │ │ │ │ │ └── xTestComposite │ │ │ │ │ │ ├── xTestComposite.psd1 │ │ │ │ │ │ └── xTestComposite.schema.psm1 │ │ │ │ │ └── xTestCompositeDsc.psd1 │ │ │ └── xTestClassDsc │ │ │ │ └── 1.0.0 │ │ │ │ ├── xTestClassDsc.psd1 │ │ │ │ └── xTestClassDsc.psm1 │ │ └── tasks │ │ │ └── main.yml │ │ ├── win_find │ │ ├── aliases │ │ ├── meta │ │ │ └── main.yml │ │ └── defaults │ │ │ └── main.yml │ │ ├── win_group │ │ ├── aliases │ │ ├── defaults │ │ │ └── main.yml │ │ └── tasks │ │ │ └── main.yml │ │ ├── win_hosts │ │ ├── aliases │ │ ├── meta │ │ │ └── main.yml │ │ ├── defaults │ │ │ └── main.yml │ │ └── tasks │ │ │ └── main.yml │ │ ├── win_owner │ │ ├── aliases │ │ ├── meta │ │ │ └── main.yml │ │ └── defaults │ │ │ └── main.yml │ │ ├── win_path │ │ └── aliases │ │ ├── win_ping │ │ ├── aliases │ │ └── tasks │ │ │ └── main.yml │ │ ├── win_reboot │ │ ├── aliases │ │ ├── meta │ │ │ └── main.yml │ │ ├── templates │ │ │ └── post_reboot.ps1 │ │ └── tasks │ │ │ └── main.yml │ │ ├── win_region │ │ └── aliases │ │ ├── win_route │ │ ├── aliases │ │ ├── defaults │ │ │ └── main.yml │ │ └── tasks │ │ │ └── main.yml │ │ ├── win_share │ │ ├── aliases │ │ ├── defaults │ │ │ └── main.yml │ │ └── tasks │ │ │ └── main.yml │ │ ├── win_shell │ │ └── aliases │ │ ├── win_slurp │ │ ├── aliases │ │ ├── defaults │ │ │ └── main.yml │ │ └── handlers │ │ │ └── main.yml │ │ ├── win_stat │ │ ├── aliases │ │ ├── meta │ │ │ └── main.yml │ │ ├── defaults │ │ │ └── main.yml │ │ └── library │ │ │ └── test_symlink_file.ps1 │ │ ├── win_user │ │ ├── aliases │ │ ├── defaults │ │ │ └── main.yml │ │ ├── files │ │ │ └── lockout_user.ps1 │ │ └── tasks │ │ │ └── main.yml │ │ ├── win_whoami │ │ └── aliases │ │ ├── win_audit_rule │ │ ├── aliases │ │ ├── defaults │ │ │ └── main.yml │ │ └── tasks │ │ │ └── main.yml │ │ ├── win_auto_logon │ │ ├── aliases │ │ ├── defaults │ │ │ └── main.yml │ │ └── tasks │ │ │ └── main.yml │ │ ├── win_command │ │ ├── aliases │ │ ├── meta │ │ │ └── main.yml │ │ └── files │ │ │ └── crt_setmode.c │ │ ├── win_credential │ │ ├── aliases │ │ ├── meta │ │ │ └── main.yml │ │ ├── files │ │ │ └── cert.pfx │ │ ├── defaults │ │ │ └── main.yml │ │ └── tasks │ │ │ └── main.yml │ │ ├── win_dhcp_lease │ │ ├── aliases │ │ ├── defaults │ │ │ └── main.yml │ │ └── tasks │ │ │ ├── main.yml │ │ │ └── tests_checkmode.yml │ │ ├── win_dns_client │ │ ├── aliases │ │ └── meta │ │ │ └── main.yml │ │ ├── win_dns_record │ │ ├── aliases │ │ ├── defaults │ │ │ └── main.yml │ │ └── tasks │ │ │ ├── main.yml │ │ │ ├── clean.yml │ │ │ └── tests.yml │ │ ├── win_dns_zone │ │ ├── aliases │ │ ├── tasks │ │ │ └── main.yml │ │ └── defaults │ │ │ └── main.yml │ │ ├── win_environment │ │ ├── aliases │ │ ├── tasks │ │ │ └── cleanup.yml │ │ └── defaults │ │ │ └── main.yml │ │ ├── win_eventlog │ │ ├── aliases │ │ └── tasks │ │ │ └── main.yml │ │ ├── win_feature │ │ ├── aliases │ │ └── defaults │ │ │ └── main.yml │ │ ├── win_firewall │ │ ├── aliases │ │ └── tasks │ │ │ └── main.yml │ │ ├── win_hostname │ │ ├── aliases │ │ ├── defaults │ │ │ └── main.yml │ │ └── tasks │ │ │ ├── main.yml │ │ │ └── test.yml │ │ ├── win_http_proxy │ │ ├── aliases │ │ └── tasks │ │ │ └── main.yml │ │ ├── win_inet_proxy │ │ ├── aliases │ │ └── tasks │ │ │ └── main.yml │ │ ├── win_package │ │ ├── aliases │ │ ├── meta │ │ │ └── main.yml │ │ ├── templates │ │ │ ├── umount.txt.j2 │ │ │ ├── mount_readonly.txt.j2 │ │ │ ├── mount.txt.j2 │ │ │ └── registry_package.ps1.j2 │ │ ├── handlers │ │ │ └── main.yml │ │ ├── files │ │ │ ├── bad.wsx │ │ │ ├── good.wsx │ │ │ └── reboot.wsx │ │ ├── library │ │ │ └── prereq_setup.ps1 │ │ └── defaults │ │ │ └── main.yml │ │ ├── win_powershell │ │ ├── aliases │ │ ├── meta │ │ │ └── main.yml │ │ ├── files │ │ │ └── test-script.ps1 │ │ └── tasks │ │ │ └── main.yml │ │ ├── win_reg_stat │ │ ├── aliases │ │ ├── meta │ │ │ └── main.yml │ │ ├── defaults │ │ │ └── main.yml │ │ ├── tasks │ │ │ └── main.yml │ │ └── templates │ │ │ └── test_reg.reg.j2 │ │ ├── win_regedit │ │ ├── aliases │ │ ├── defaults │ │ │ └── main.yml │ │ └── tasks │ │ │ └── cleanup.yml │ │ ├── win_service │ │ ├── aliases │ │ ├── files │ │ │ └── Program.cs │ │ ├── defaults │ │ │ └── main.yml │ │ └── tasks │ │ │ ├── driver.yml │ │ │ ├── sid_info.yml │ │ │ ├── service_type.yml │ │ │ ├── error_control.yml │ │ │ ├── pre_shutdown_timeout_ms.yml │ │ │ └── load_order_group.yml │ │ ├── win_tempfile │ │ ├── aliases │ │ └── defaults │ │ │ └── main.yml │ │ ├── win_template │ │ ├── aliases │ │ ├── vars │ │ │ └── main.yml │ │ ├── meta │ │ │ └── main.yml │ │ └── templates │ │ │ ├── foo.j2 │ │ │ ├── foo.utf-8.j2 │ │ │ ├── foo2.j2 │ │ │ ├── another_foo.j2 │ │ │ └── with_managed.j2 │ │ ├── win_timezone │ │ ├── aliases │ │ └── tasks │ │ │ └── main.yml │ │ ├── win_updates │ │ ├── aliases │ │ └── meta │ │ │ └── main.yml │ │ ├── win_user_right │ │ ├── aliases │ │ ├── defaults │ │ │ └── main.yml │ │ ├── tasks │ │ │ └── main.yml │ │ └── library │ │ │ └── test_get_right.ps1 │ │ ├── win_acl_inheritance │ │ ├── aliases │ │ ├── defaults │ │ │ └── main.yml │ │ └── library │ │ │ └── test_get_acl.ps1 │ │ ├── win_certificate_info │ │ ├── aliases │ │ ├── meta │ │ │ └── main.yml │ │ ├── defaults │ │ │ └── main.yml │ │ └── files │ │ │ ├── subj-cert.pem │ │ │ └── root-cert.pem │ │ ├── win_feature_info │ │ ├── aliases │ │ ├── defaults │ │ │ └── main.yml │ │ └── tasks │ │ │ └── main.yml │ │ ├── win_file_compression │ │ ├── aliases │ │ ├── meta │ │ │ └── main.yml │ │ └── defaults │ │ │ └── main.yml │ │ ├── win_get_url │ │ ├── files │ │ │ └── ftp │ │ │ │ ├── anon │ │ │ │ ├── file.txt │ │ │ │ ├── file2.txt │ │ │ │ ├── sha1sum.txt │ │ │ │ ├── sha256sum.txt │ │ │ │ └── sha256sum_with_dot.txt │ │ │ │ ├── user │ │ │ │ └── file.txt │ │ │ │ └── user-pass │ │ │ │ └── file.txt │ │ ├── aliases │ │ ├── meta │ │ │ └── main.yml │ │ ├── templates │ │ │ └── slimftpd.conf.tmpl │ │ └── library │ │ │ └── win_defender_exclusion.ps1 │ │ ├── win_group_membership │ │ ├── aliases │ │ └── tasks │ │ │ └── main.yml │ │ ├── win_mapped_drive │ │ ├── aliases │ │ └── defaults │ │ │ └── main.yml │ │ ├── win_optional_feature │ │ ├── aliases │ │ └── tasks │ │ │ └── main.yml │ │ ├── win_product_facts │ │ ├── aliases │ │ └── tasks │ │ │ └── main.yml │ │ ├── win_service_info │ │ ├── aliases │ │ ├── meta │ │ │ └── main.yml │ │ ├── handlers │ │ │ └── main.yml │ │ └── defaults │ │ │ └── main.yml │ │ ├── win_user_profile │ │ ├── aliases │ │ └── tasks │ │ │ └── main.yml │ │ ├── app_control │ │ ├── aliases │ │ ├── meta │ │ │ └── main.yml │ │ ├── files │ │ │ └── test-script.ps1 │ │ ├── handlers │ │ │ └── main.yml │ │ └── tasks │ │ │ └── main.yml │ │ ├── async_status │ │ ├── aliases │ │ └── tasks │ │ │ └── main.yml │ │ ├── win_audit_policy_system │ │ ├── aliases │ │ ├── defaults │ │ │ └── main.yml │ │ └── tasks │ │ │ └── main.yml │ │ ├── win_certificate_store │ │ ├── aliases │ │ ├── meta │ │ │ └── main.yml │ │ ├── defaults │ │ │ └── main.yml │ │ └── files │ │ │ ├── subj-cert.pem │ │ │ ├── root-cert.pem │ │ │ ├── root-key.pem │ │ │ └── subj-key.pem │ │ ├── win_computer_description │ │ ├── aliases │ │ └── defaults │ │ │ └── main.yml │ │ ├── win_hotfix │ │ ├── aliases │ │ ├── defaults │ │ │ └── main.yml │ │ └── tasks │ │ │ ├── tests.yml │ │ │ └── main.yml │ │ ├── win_listen_ports_facts │ │ └── aliases │ │ ├── win_uri │ │ ├── meta │ │ │ └── main.yml │ │ └── aliases │ │ ├── win_wait_for │ │ ├── aliases │ │ ├── defaults │ │ │ └── main.yml │ │ └── files │ │ │ └── http-server.ps1 │ │ ├── module_utils_Process │ │ ├── aliases │ │ ├── meta │ │ │ └── main.yml │ │ └── tasks │ │ │ └── main.yml │ │ ├── module_utils_SCManager │ │ ├── aliases │ │ └── tasks │ │ │ └── main.yml │ │ ├── setup_http_tests │ │ ├── meta │ │ │ └── main.yml │ │ ├── defaults │ │ │ └── main.yml │ │ ├── handlers │ │ │ └── main.yml │ │ ├── vars │ │ │ └── httptester.yml │ │ └── tasks │ │ │ └── main.yml │ │ ├── module_utils_SecurityIdentifier │ │ ├── aliases │ │ └── tasks │ │ │ └── main.yml │ │ ├── module_utils_WebRequest │ │ ├── meta │ │ │ └── main.yml │ │ ├── aliases │ │ └── tasks │ │ │ └── main.yml │ │ ├── setup_win_printargv │ │ ├── meta │ │ │ └── main.yml │ │ ├── tasks │ │ │ └── main.yml │ │ └── files │ │ │ └── PrintArgv.cs │ │ ├── setup_remote_tmp_dir │ │ ├── handlers │ │ │ └── main.yml │ │ └── tasks │ │ │ └── main.yml │ │ └── setup_win_device │ │ ├── handlers │ │ └── main.yml │ │ └── tasks │ │ └── main.yml ├── requirements.yml └── sanity │ ├── ignore-2.16.txt │ ├── ignore-2.17.txt │ ├── ignore-2.18.txt │ ├── ignore-2.19.txt │ ├── ignore-2.20.txt │ └── ignore-2.21.txt ├── changelogs ├── fragments │ ├── .keep │ ├── test-utils.yml │ └── win_shell-path.yml └── config.yaml ├── plugins ├── action │ ├── __init__.py │ └── win_powershell.py ├── filter │ ├── __init__.py │ └── quote.yml ├── modules │ ├── __init__.py │ ├── win_ping.ps1 │ ├── slurp.ps1 │ ├── win_hostname.ps1 │ ├── win_hostname.py │ ├── win_ping.py │ ├── win_owner.yml │ ├── win_feature_info.ps1 │ ├── slurp.yml │ ├── win_route.py │ ├── win_product_facts.py │ ├── win_tempfile.py │ ├── win_computer_description.py │ ├── win_computer_description.ps1 │ ├── async_status.ps1 │ ├── win_timezone.py │ ├── win_auto_logon.py │ └── win_timezone.ps1 ├── doc_fragments │ └── __init__.py ├── module_utils │ └── __init__.py └── plugin_utils │ └── __init__.py ├── .vscode ├── extensions.json └── settings.json ├── codecov.yml ├── .azure-pipelines ├── commands │ ├── units.sh │ ├── sanity.sh │ ├── lint.sh │ └── windows.sh ├── scripts │ ├── time-command.py │ ├── process-results.sh │ ├── aggregate-coverage.sh │ ├── run-tests.sh │ ├── report-coverage.sh │ └── combine-coverage.py └── templates │ └── coverage.yml ├── .git-blame-ignore-revs ├── .ansible-lint ├── meta └── runtime.yml ├── .github └── workflows │ ├── stale.yml │ └── docs-push.yml ├── galaxy.yml └── docs └── docsite └── links.yml /tests/unit/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /changelogs/fragments/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /plugins/action/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /plugins/filter/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /plugins/modules/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- 1 | output/ 2 | -------------------------------------------------------------------------------- /plugins/doc_fragments/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /plugins/module_utils/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /plugins/plugin_utils/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/unit/plugins/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/integration/targets/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/unit/plugins/action/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/unit/plugins/filter/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/integration/targets/win_copy/files/empty.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/integration/targets/win_file/files/foobar/fileB: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/integration/targets/win_copy/files/foo.txt: -------------------------------------------------------------------------------- 1 | foo.txt 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_copy/files/subdir/bar.txt: -------------------------------------------------------------------------------- 1 | baz 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_file/files/foo.txt: -------------------------------------------------------------------------------- 1 | foo.txt 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_file/files/foobar/directory/fileC: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/integration/targets/win_file/files/foobar/directory/fileD: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/integration/targets/win_file/files/foobar/fileA: -------------------------------------------------------------------------------- 1 | fileA 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_setup/files/false_fact.ps1: -------------------------------------------------------------------------------- 1 | $false 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_setup/files/true_fact.ps1: -------------------------------------------------------------------------------- 1 | $true 2 | -------------------------------------------------------------------------------- /tests/requirements.yml: -------------------------------------------------------------------------------- 1 | collections: 2 | - name: microsoft.ad 3 | -------------------------------------------------------------------------------- /tests/integration/targets/win_acl/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group2 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_async/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group1 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_copy/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group3 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_copy/files/subdir/subdir2/baz.txt: -------------------------------------------------------------------------------- 1 | baz 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_dsc/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group3 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_file/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group1 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_find/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group3 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_group/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group2 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_hosts/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group1 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_owner/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group3 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_path/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group1 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_ping/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group2 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_reboot/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group3 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_region/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group3 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_route/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group5 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_setup/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group3 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_share/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group3 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_shell/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group1 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_slurp/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group3 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_stat/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group3 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_user/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group2 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_whoami/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group2 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_audit_rule/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group2 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_auto_logon/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group4 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_command/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group2 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_credential/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group2 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_dhcp_lease/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group4 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_dns_client/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group1 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_dns_record/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group4 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_dns_zone/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group4 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_environment/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group2 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_eventlog/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group2 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_feature/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group1 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_firewall/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group1 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_hostname/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group2 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_http_proxy/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group1 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_inet_proxy/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group2 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_package/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group1 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_powershell/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group1 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_reg_stat/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group3 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_regedit/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group2 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_service/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group2 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_tempfile/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group1 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_template/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group2 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_timezone/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group2 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_updates/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group1 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_user_right/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group3 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_acl_inheritance/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group3 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_certificate_info/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group3 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_copy/files/subdir/subdir2/subdir3/subdir4/qux.txt: -------------------------------------------------------------------------------- 1 | qux -------------------------------------------------------------------------------- /tests/integration/targets/win_feature_info/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group4 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_file_compression/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group1 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_get_url/files/ftp/anon/file.txt: -------------------------------------------------------------------------------- 1 | ftp/anon/file.txt 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_get_url/files/ftp/user/file.txt: -------------------------------------------------------------------------------- 1 | ftp/user/file.txt 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_group_membership/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group1 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_mapped_drive/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group5 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_optional_feature/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group2 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_product_facts/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group1 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_service_info/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group1 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_user_profile/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group4 2 | -------------------------------------------------------------------------------- /tests/integration/targets/app_control/aliases: -------------------------------------------------------------------------------- 1 | windows 2 | shippable/windows/group1 3 | -------------------------------------------------------------------------------- /tests/integration/targets/async_status/aliases: -------------------------------------------------------------------------------- 1 | windows 2 | shippable/windows/group1 3 | -------------------------------------------------------------------------------- /tests/integration/targets/win_audit_policy_system/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group3 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_certificate_store/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group4 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_computer_description/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group2 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_get_url/files/ftp/anon/file2.txt: -------------------------------------------------------------------------------- 1 | ftp/anon/file2.txt 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_hotfix/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group2 2 | unstable 3 | -------------------------------------------------------------------------------- /tests/integration/targets/win_listen_ports_facts/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group5 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_stat/meta/main.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - setup_remote_tmp_dir -------------------------------------------------------------------------------- /tests/integration/targets/win_uri/meta/main.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - setup_http_tests 3 | -------------------------------------------------------------------------------- /tests/integration/targets/win_wait_for/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group1 2 | unstable 3 | -------------------------------------------------------------------------------- /tests/integration/targets/win_acl/meta/main.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - setup_remote_tmp_dir 3 | -------------------------------------------------------------------------------- /tests/integration/targets/win_file/meta/main.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - setup_remote_tmp_dir 3 | -------------------------------------------------------------------------------- /tests/integration/targets/win_find/meta/main.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - setup_remote_tmp_dir 3 | -------------------------------------------------------------------------------- /tests/integration/targets/win_get_url/files/ftp/user-pass/file.txt: -------------------------------------------------------------------------------- 1 | ftp/user-pass/file.txt 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_group/defaults/main.yml: -------------------------------------------------------------------------------- 1 | test_win_group_name: Ansiblings 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_template/vars/main.yml: -------------------------------------------------------------------------------- 1 | templated_var: templated_var_loaded 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_uri/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group2 2 | needs/httptester 3 | -------------------------------------------------------------------------------- /tests/integration/targets/app_control/meta/main.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - setup_remote_tmp_dir 3 | -------------------------------------------------------------------------------- /tests/integration/targets/module_utils_Process/aliases: -------------------------------------------------------------------------------- 1 | windows 2 | shippable/windows/group2 3 | -------------------------------------------------------------------------------- /tests/integration/targets/module_utils_SCManager/aliases: -------------------------------------------------------------------------------- 1 | windows 2 | shippable/windows/group2 3 | -------------------------------------------------------------------------------- /tests/integration/targets/win_command/meta/main.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - setup_win_printargv 3 | -------------------------------------------------------------------------------- /tests/integration/targets/win_dns_client/meta/main.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - setup_win_device 3 | -------------------------------------------------------------------------------- /tests/integration/targets/win_get_url/aliases: -------------------------------------------------------------------------------- 1 | shippable/windows/group1 2 | needs/httptester 3 | -------------------------------------------------------------------------------- /tests/integration/targets/win_hosts/meta/main.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - setup_remote_tmp_dir 3 | -------------------------------------------------------------------------------- /tests/integration/targets/win_owner/meta/main.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - setup_remote_tmp_dir 3 | -------------------------------------------------------------------------------- /tests/integration/targets/win_package/meta/main.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - setup_remote_tmp_dir 3 | -------------------------------------------------------------------------------- /tests/integration/targets/win_reboot/meta/main.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - setup_remote_tmp_dir 3 | -------------------------------------------------------------------------------- /tests/integration/targets/win_reg_stat/meta/main.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - setup_remote_tmp_dir 3 | -------------------------------------------------------------------------------- /tests/integration/targets/win_setup/meta/main.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - setup_remote_tmp_dir 3 | -------------------------------------------------------------------------------- /tests/integration/targets/win_template/meta/main.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - setup_remote_tmp_dir 3 | -------------------------------------------------------------------------------- /tests/integration/targets/win_template/templates/foo.j2: -------------------------------------------------------------------------------- 1 | BEGIN 2 | {{ templated_var }} 3 | END 4 | -------------------------------------------------------------------------------- /tests/integration/targets/win_template/templates/foo.utf-8.j2: -------------------------------------------------------------------------------- 1 | —café— - {{ templated_var }} 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_template/templates/foo2.j2: -------------------------------------------------------------------------------- 1 | BEGIN 2 | [% templated_var %] 3 | END 4 | -------------------------------------------------------------------------------- /tests/integration/targets/win_updates/meta/main.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - setup_remote_tmp_dir 3 | -------------------------------------------------------------------------------- /tests/integration/targets/module_utils_Process/meta/main.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - setup_win_printargv -------------------------------------------------------------------------------- /tests/integration/targets/setup_http_tests/meta/main.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - setup_remote_tmp_dir 3 | -------------------------------------------------------------------------------- /tests/integration/targets/win_credential/meta/main.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - setup_remote_tmp_dir 3 | -------------------------------------------------------------------------------- /tests/integration/targets/win_feature_info/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | test_feature: Telnet-Client 3 | -------------------------------------------------------------------------------- /tests/integration/targets/win_hostname/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | test_win_hostname_name: abcdef-123 3 | -------------------------------------------------------------------------------- /tests/integration/targets/win_powershell/meta/main.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - setup_remote_tmp_dir 3 | -------------------------------------------------------------------------------- /tests/integration/targets/win_service_info/meta/main.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - setup_remote_tmp_dir 3 | -------------------------------------------------------------------------------- /tests/integration/targets/win_setup/files/other_facts.ps1: -------------------------------------------------------------------------------- 1 | @( 2 | "abc", 3 | "def" 4 | ) 5 | -------------------------------------------------------------------------------- /tests/integration/targets/win_template/templates/another_foo.j2: -------------------------------------------------------------------------------- 1 | ABC 2 | {{ templated_var }} 3 | DEF 4 | -------------------------------------------------------------------------------- /tests/integration/targets/module_utils_SecurityIdentifier/aliases: -------------------------------------------------------------------------------- 1 | windows 2 | shippable/windows/group1 3 | -------------------------------------------------------------------------------- /tests/integration/targets/module_utils_WebRequest/meta/main.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - setup_http_tests 3 | -------------------------------------------------------------------------------- /tests/integration/targets/setup_win_printargv/meta/main.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - setup_remote_tmp_dir 3 | -------------------------------------------------------------------------------- /tests/integration/targets/win_certificate_info/meta/main.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - setup_remote_tmp_dir 3 | -------------------------------------------------------------------------------- /tests/integration/targets/win_certificate_store/meta/main.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - setup_remote_tmp_dir 3 | -------------------------------------------------------------------------------- /tests/integration/targets/win_file_compression/meta/main.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - setup_remote_tmp_dir 3 | -------------------------------------------------------------------------------- /tests/integration/targets/win_reg_stat/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | test_reg_path: Test Key / [&Ansible*] 3 | -------------------------------------------------------------------------------- /tests/integration/targets/win_user_right/defaults/main.yml: -------------------------------------------------------------------------------- 1 | test_win_user_right_name: SeRelabelPrivilege 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_package/templates/umount.txt.j2: -------------------------------------------------------------------------------- 1 | select vdisk file="{{ path }}" 2 | 3 | detach vdisk -------------------------------------------------------------------------------- /tests/integration/targets/win_setup/files/will_skip.txt: -------------------------------------------------------------------------------- 1 | some dummy text, won't run as it doesn't end with .ps1 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_slurp/defaults/main.yml: -------------------------------------------------------------------------------- 1 | test_win_slurp_dir: C:\ansible\win_slurp .ÅÑŚÌβŁÈ [$!@^&test(;)] -------------------------------------------------------------------------------- /tests/integration/targets/module_utils_WebRequest/aliases: -------------------------------------------------------------------------------- 1 | windows 2 | shippable/windows/group1 3 | needs/httptester 4 | -------------------------------------------------------------------------------- /tests/integration/targets/win_copy/defaults/main.yml: -------------------------------------------------------------------------------- 1 | test_win_copy_path: C:\ansible\win_copy .ÅÑŚÌβŁÈ [$!@^&test(;)] 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_get_url/meta/main.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - setup_remote_tmp_dir 3 | - setup_http_tests 4 | -------------------------------------------------------------------------------- /tests/integration/targets/win_package/templates/mount_readonly.txt.j2: -------------------------------------------------------------------------------- 1 | select vdisk file="{{ path }}" 2 | 3 | attach vdisk readonly -------------------------------------------------------------------------------- /tests/integration/targets/win_tempfile/defaults/main.yml: -------------------------------------------------------------------------------- 1 | test_tempfile_path: 'C:\ansible\win_tempfile .ÅÑŚÌβŁÈ [$!@^&test(;)]' 2 | -------------------------------------------------------------------------------- /tests/integration/targets/win_route/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | default_gateway: 192.168.1.1 3 | destination_ip_address: 192.168.2.10 4 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "ms-python.python", 4 | "ms-vscode.powershell", 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /tests/integration/targets/win_wait_for/defaults/main.yml: -------------------------------------------------------------------------------- 1 | test_win_wait_for_path: C:\ansible\win_wait_for 2 | test_win_wait_for_port: 1234 3 | -------------------------------------------------------------------------------- /tests/integration/targets/win_dns_zone/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Run Defined Test Flow 3 | include_tasks: "{{ win_dns_zone_test_type }}.yml" 4 | -------------------------------------------------------------------------------- /tests/integration/targets/win_template/templates/with_managed.j2: -------------------------------------------------------------------------------- 1 | {{ ansible_managed }} # NB: no line ending on this template to avoid line-ending issues -------------------------------------------------------------------------------- /tests/integration/targets/win_feature/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # Feature not normally installed by default. 4 | test_win_feature_name: Telnet-Client 5 | -------------------------------------------------------------------------------- /tests/integration/targets/win_find/defaults/main.yml: -------------------------------------------------------------------------------- 1 | win_find_dir: '{{ remote_tmp_dir }}\win_find .ÅÑŚÌβŁÈ [$!@^&test(;)]' 2 | test_win_find_username: testuser 3 | -------------------------------------------------------------------------------- /tests/unit/test_data/win_updates/fail_poll_script.txt: -------------------------------------------------------------------------------- 1 | {"msg": "Error message during polling", "failed": true, "changed": false} 2 | 3 | {"changed": false} 4 | -------------------------------------------------------------------------------- /changelogs/fragments/test-utils.yml: -------------------------------------------------------------------------------- 1 | bugfixes: 2 | - >- 3 | Stop using the deprecated text module_utils in Ansible that will be removed in Ansible ``2.24``. 4 | -------------------------------------------------------------------------------- /tests/integration/targets/win_dsc/meta/main.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - setup_remote_tmp_dir 3 | galaxy_info: 4 | role_name: win_dsc 5 | namespace: win_dsc_ns 6 | -------------------------------------------------------------------------------- /tests/integration/targets/win_slurp/handlers/main.yml: -------------------------------------------------------------------------------- 1 | - name: remove test directory 2 | win_file: 3 | path: '{{ test_win_slurp_dir }}' 4 | state: absent 5 | -------------------------------------------------------------------------------- /tests/integration/targets/setup_remote_tmp_dir/handlers/main.yml: -------------------------------------------------------------------------------- 1 | - name: delete temporary directory 2 | win_file: 3 | path: '{{ remote_tmp_dir }}' 4 | state: absent 5 | -------------------------------------------------------------------------------- /tests/integration/targets/win_owner/defaults/main.yml: -------------------------------------------------------------------------------- 1 | test_win_owner_path: '{{ remote_tmp_dir }}\win_owner .ÅÑŚÌβŁÈ [$!@^&test(;)]' 2 | test_win_owner_user: test win owner 3 | -------------------------------------------------------------------------------- /tests/integration/targets/win_setup/files/my_facts.ps1: -------------------------------------------------------------------------------- 1 | @{ 2 | my_custom_fact = 'value' 3 | my_complex_custom_fact = @{ 4 | hello = 'world' 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tests/integration/targets/win_credential/files/cert.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ansible-collections/ansible.windows/HEAD/tests/integration/targets/win_credential/files/cert.pfx -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | --- 2 | ignore: 3 | - .azure-pipelines 4 | - tests/unit/**/conftest.py 5 | - tests/unit/conftest.py 6 | 7 | fixes: 8 | - "/ansible_collections/ansible/windows/::" 9 | -------------------------------------------------------------------------------- /tests/integration/targets/win_setup/files/json_facts.json: -------------------------------------------------------------------------------- 1 | { 2 | "my_json_custom_fact": "value", 3 | "my_json_complex_custom_fact": { 4 | "hello": "world" 5 | } 6 | } -------------------------------------------------------------------------------- /tests/integration/targets/win_stat/defaults/main.yml: -------------------------------------------------------------------------------- 1 | win_stat_dir: '{{ remote_tmp_dir }}\win_stat' 2 | win_stat_underprivileged_dir: C:\ansible\win_stat 3 | win_stat_user: test-stat 4 | -------------------------------------------------------------------------------- /tests/unit/test_data/win_updates/fail_poll_script_critical_stdout.txt: -------------------------------------------------------------------------------- 1 | {"failed": true, "changed": false, "rc": 1, "stdout": "stdout data", "stderr": "stderr data"} 2 | 3 | {"changed": false} 4 | -------------------------------------------------------------------------------- /tests/integration/targets/win_audit_policy_system/defaults/main.yml: -------------------------------------------------------------------------------- 1 | #important that the subcategory is from a different category 2 | category_name: detailed tracking 3 | subcategory_name: file system 4 | -------------------------------------------------------------------------------- /tests/integration/targets/win_service_info/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: remove test service 3 | win_service: 4 | name: '{{ item }}' 5 | state: absent 6 | loop: '{{ service_names }}' 7 | -------------------------------------------------------------------------------- /tests/integration/targets/win_user/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | test_win_user_name: test_win_user 4 | test_win_user_password: "T35Tus3rP@ssW0rd" 5 | test_win_user_password2: "pa55wOrd4te5tU53R!" 6 | -------------------------------------------------------------------------------- /tests/sanity/ignore-2.16.txt: -------------------------------------------------------------------------------- 1 | tests/integration/targets/win_dsc/files/xTestCompositeDsc/1.0.0/DSCResources/xTestComposite/xTestComposite.schema.psm1 pslint!skip # Pwsh cannot parse DSC to MOF on Linux 2 | -------------------------------------------------------------------------------- /tests/sanity/ignore-2.17.txt: -------------------------------------------------------------------------------- 1 | tests/integration/targets/win_dsc/files/xTestCompositeDsc/1.0.0/DSCResources/xTestComposite/xTestComposite.schema.psm1 pslint!skip # Pwsh cannot parse DSC to MOF on Linux 2 | -------------------------------------------------------------------------------- /tests/sanity/ignore-2.18.txt: -------------------------------------------------------------------------------- 1 | tests/integration/targets/win_dsc/files/xTestCompositeDsc/1.0.0/DSCResources/xTestComposite/xTestComposite.schema.psm1 pslint!skip # Pwsh cannot parse DSC to MOF on Linux 2 | -------------------------------------------------------------------------------- /tests/sanity/ignore-2.19.txt: -------------------------------------------------------------------------------- 1 | tests/integration/targets/win_dsc/files/xTestCompositeDsc/1.0.0/DSCResources/xTestComposite/xTestComposite.schema.psm1 pslint!skip # Pwsh cannot parse DSC to MOF on Linux 2 | -------------------------------------------------------------------------------- /tests/sanity/ignore-2.20.txt: -------------------------------------------------------------------------------- 1 | tests/integration/targets/win_dsc/files/xTestCompositeDsc/1.0.0/DSCResources/xTestComposite/xTestComposite.schema.psm1 pslint!skip # Pwsh cannot parse DSC to MOF on Linux 2 | -------------------------------------------------------------------------------- /tests/sanity/ignore-2.21.txt: -------------------------------------------------------------------------------- 1 | tests/integration/targets/win_dsc/files/xTestCompositeDsc/1.0.0/DSCResources/xTestComposite/xTestComposite.schema.psm1 pslint!skip # Pwsh cannot parse DSC to MOF on Linux 2 | -------------------------------------------------------------------------------- /tests/integration/targets/setup_win_device/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: remove dummy network adapter device 3 | win_device: 4 | name: '{{ network_device_name_raw.name }}' 5 | state: absent 6 | -------------------------------------------------------------------------------- /tests/integration/targets/win_auto_logon/defaults/main.yml: -------------------------------------------------------------------------------- 1 | # This doesn't have to be valid, just testing weird chars in the pass 2 | test_logon_password: 'Gokupass123' 3 | test_logon_password2: 'Over9000' 4 | -------------------------------------------------------------------------------- /tests/integration/targets/setup_http_tests/defaults/main.yml: -------------------------------------------------------------------------------- 1 | badssl_host: wrong.host.badssl.com 2 | httpbin_host: httpbin.org 3 | sni_host: ci-files.testing.ansible.com 4 | badssl_host_substring: wrong.host.badssl.com 5 | -------------------------------------------------------------------------------- /tests/unit/requirements.txt: -------------------------------------------------------------------------------- 1 | setuptools > 0.6 # pytest-xdist installed via requirements does not work with very old setuptools (sanity_ok) 2 | unittest2 ; python_version < '2.7' 3 | importlib ; python_version < '2.7' 4 | -------------------------------------------------------------------------------- /.azure-pipelines/commands/units.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o pipefail -eux 4 | 5 | # shellcheck disable=SC2086 6 | ansible-test units --color -v --docker default ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} 7 | 8 | -------------------------------------------------------------------------------- /tests/integration/targets/win_dns_record/defaults/main.yml: -------------------------------------------------------------------------------- 1 | win_dns_record_zone: test.ansible.local 2 | win_dns_record_revzone: 0.0.255.in-addr.arpa 3 | win_dns_record_revzone_network: 255.0.0.0/24 4 | win_dns_zone_scope: external 5 | -------------------------------------------------------------------------------- /.git-blame-ignore-revs: -------------------------------------------------------------------------------- 1 | # .git-blame-ignore-revs 2 | # Bulk PowerShell sanity fixes PSSA 1.20.0 3 | 55653aa4b8bbd43c9227ddc949941ab7b9ed9dfe 4 | # Bulk PowerShell sanity fixes PSSA 1.21.0 5 | 81d0bdccd643c6d97d7927446df4f51f0b99d708 6 | -------------------------------------------------------------------------------- /tests/integration/targets/win_powershell/files/test-script.ps1: -------------------------------------------------------------------------------- 1 | [CmdletBinding()] 2 | param ( 3 | [Parameter(Mandatory)] 4 | [string] 5 | $Name 6 | ) 7 | 8 | @{ 9 | Name = $Name 10 | Unicode = 'ü' 11 | } 12 | -------------------------------------------------------------------------------- /tests/integration/targets/win_get_url/files/ftp/anon/sha1sum.txt: -------------------------------------------------------------------------------- 1 | a97e6837f60cec6da4491bab387296bbcd72bdba cHR1eA== 2 | 3911340502960ca33aece01129234460bfeb2791 not_target1.txt 3 | 1b4b6adf30992cedb0f6edefd6478ff0a593b2e4 not_target2.txt 4 | -------------------------------------------------------------------------------- /tests/integration/targets/win_regedit/defaults/main.yml: -------------------------------------------------------------------------------- 1 | test_win_regedit_local_key: 'HKLM:\Software\Moo []{}!@#$%^&*()-_=+/key''"?<>' 2 | test_win_regedit_classes_key: HKCR:\.test-ansible 3 | test_win_regedit_hive_key: HKLM:\ANSIBLE\NewKey 4 | -------------------------------------------------------------------------------- /tests/integration/targets/win_copy/files-different/vault/readme.txt: -------------------------------------------------------------------------------- 1 | This directory contains some files that have been encrypted with ansible-vault. 2 | 3 | This is to test out the decrypt parameter in win_copy. 4 | 5 | The password is: password 6 | -------------------------------------------------------------------------------- /tests/integration/targets/app_control/files/test-script.ps1: -------------------------------------------------------------------------------- 1 | [CmdletBinding()] 2 | param ( 3 | [string] 4 | $Value 5 | ) 6 | 7 | @{ 8 | language_mode = $ExecutionContext.SessionState.LanguageMode.ToString() 9 | ünicode = $Value 10 | } 11 | -------------------------------------------------------------------------------- /tests/integration/targets/win_file_compression/defaults/main.yml: -------------------------------------------------------------------------------- 1 | test_win_file_compression_suffix: win_file_compression .ÅÑŚÌβŁÈ [$!@^&test(;)] 2 | test_win_file_compression_sub_directories: 3 | - 'a' 4 | - 'b' 5 | test_win_file_compression_filename: 'foo.bar' 6 | -------------------------------------------------------------------------------- /tests/integration/targets/win_certificate_info/defaults/main.yml: -------------------------------------------------------------------------------- 1 | win_cert_dir: '{{ remote_tmp_dir }}\win_certificate .ÅÑŚÌβŁÈ [$!@^&test(;)]' 2 | subj_thumbprint: 'BD7AF104CF1872BDB518D95C9534EA941665FD27' 3 | root_thumbprint: 'BC05633694E675449136679A658281F17A191087' 4 | -------------------------------------------------------------------------------- /tests/integration/targets/module_utils_SCManager/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: test SCManager.cs 3 | scmanager_tests: 4 | register: scmanager_test 5 | 6 | - name: assert test SCManager.cs 7 | assert: 8 | that: 9 | - scmanager_test.data == "success" 10 | -------------------------------------------------------------------------------- /tests/integration/targets/win_package/templates/mount.txt.j2: -------------------------------------------------------------------------------- 1 | create vdisk file="{{ path }}" maximum=128 type=fixed 2 | 3 | attach vdisk 4 | 5 | convert mbr 6 | 7 | create partition primary 8 | 9 | format FS=NTFS label=FATDrive quick 10 | 11 | assign letter="{{ drive }}" -------------------------------------------------------------------------------- /tests/integration/targets/setup_http_tests/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: remove CA trust store cert 3 | win_certificate_store: 4 | thumbprint: '{{ httptester_ca_cert_info.thumbprints[0] }}' 5 | state: absent 6 | store_location: LocalMachine 7 | store_name: Root 8 | -------------------------------------------------------------------------------- /tests/integration/targets/win_computer_description/defaults/main.yml: -------------------------------------------------------------------------------- 1 | test_description: description 1 2 | test_organization: organization name 1 3 | test_owner: owner name 1 4 | test_description2: description 2 5 | test_organization2: organization name 2 6 | test_owner2: owner name 2 7 | -------------------------------------------------------------------------------- /tests/integration/targets/win_certificate_store/defaults/main.yml: -------------------------------------------------------------------------------- 1 | win_cert_dir: '{{ remote_tmp_dir }}\win_certificate .ÅÑŚÌβŁÈ [$!@^&test(;)]' 2 | key_password: password 3 | subj_thumbprint: 'BD7AF104CF1872BDB518D95C9534EA941665FD27' 4 | root_thumbprint: 'BC05633694E675449136679A658281F17A191087' 5 | -------------------------------------------------------------------------------- /tests/integration/targets/win_dsc/files/xTestDsc/1.0.0/DSCResources/ANSIBLE_xSetReboot/ANSIBLE_xSetReboot.schema.mof: -------------------------------------------------------------------------------- 1 | [ClassVersion("1.0.0"), FriendlyName("xSetReboot")] 2 | class ANSIBLE_xSetReboot : OMI_BaseResource 3 | { 4 | [Key] String KeyParam; 5 | [Write] Boolean Value; 6 | }; 7 | 8 | -------------------------------------------------------------------------------- /tests/integration/targets/setup_http_tests/vars/httptester.yml: -------------------------------------------------------------------------------- 1 | # these are fake hostnames provided by docker link for the httptester container 2 | badssl_host: fail.ansible.http.tests 3 | httpbin_host: ansible.http.tests 4 | sni_host: sni1.ansible.http.tests 5 | badssl_host_substring: HTTP Client Testing Service 6 | -------------------------------------------------------------------------------- /tests/integration/targets/win_get_url/files/ftp/anon/sha256sum.txt: -------------------------------------------------------------------------------- 1 | b1b6ce5073c8fac263a8fc5edfffdbd5dec1980c784e09c5bc69f8fb6056f006 cHR1eA== 2 | 30949cc401e30ac494d695ab8764a9f76aae17c5d73c67f65e9b558f47eff892 not_target1.txt 3 | d0dbfc1945bc83bf6606b770e442035f2c4e15c886ee0c22fb3901ba19900b5b not_target2.txt 4 | -------------------------------------------------------------------------------- /tests/integration/targets/win_hosts/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | test_win_hosts_cname: testhost 3 | test_win_hosts_ip: 192.168.168.1 4 | 5 | test_win_hosts_aliases_set: 6 | - alias1 7 | - alias2 8 | - alias3 9 | - alias4 10 | 11 | test_win_hosts_aliases_remove: 12 | - alias3 13 | - alias4 14 | -------------------------------------------------------------------------------- /tests/integration/targets/win_dhcp_lease/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dhcp_lease_ip: 172.16.98.230 3 | dhcp_scope_id: 172.16.98.0 4 | dhcp_scope_start: 172.16.98.2 5 | dhcp_scope_end: 172.16.98.254 6 | dhcp_scope_subnet_mask: 255.255.255.0 7 | dhcp_lease_mac: 0A-0B-0C-04-05-AA 8 | dhcp_lease_hostname: fancy-reservation 9 | -------------------------------------------------------------------------------- /tests/integration/targets/module_utils_WebRequest/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: test WebRequest 3 | web_request_test: 4 | httpbin_host: '{{ httpbin_host }}' 5 | register: web_request 6 | 7 | - name: assert test WebRequest succeeded 8 | assert: 9 | that: 10 | - web_request.data == 'success' 11 | -------------------------------------------------------------------------------- /tests/integration/targets/win_get_url/files/ftp/anon/sha256sum_with_dot.txt: -------------------------------------------------------------------------------- 1 | b1b6ce5073c8fac263a8fc5edfffdbd5dec1980c784e09c5bc69f8fb6056f006 ./cHR1eA== 2 | 30949cc401e30ac494d695ab8764a9f76aae17c5d73c67f65e9b558f47eff892 ./not_target1.txt 3 | d0dbfc1945bc83bf6606b770e442035f2c4e15c886ee0c22fb3901ba19900b5b ./not_target2.txt 4 | -------------------------------------------------------------------------------- /tests/integration/targets/win_eventlog/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Run tests for win_eventlog in normal mode 2 | import_tasks: tests.yml 3 | vars: 4 | in_check_mode: no 5 | 6 | - name: Run tests for win_eventlog in check-mode 7 | import_tasks: tests.yml 8 | vars: 9 | in_check_mode: yes 10 | check_mode: yes 11 | -------------------------------------------------------------------------------- /tests/integration/targets/setup_remote_tmp_dir/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: create temporary directory 2 | win_tempfile: 3 | state: directory 4 | suffix: .test 5 | register: remote_tmp_dir 6 | notify: 7 | - delete temporary directory 8 | 9 | - name: record temporary directory 10 | set_fact: 11 | remote_tmp_dir: "{{ remote_tmp_dir.path }}" 12 | -------------------------------------------------------------------------------- /tests/integration/targets/win_async/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: check that a job can deserialize large data 2 | win_shell: '"a" * 2097152' 3 | async: 60 4 | register: async_large_output 5 | no_log: true 6 | 7 | - name: assert output can deserialize large data 8 | assert: 9 | that: 10 | - async_large_output.stdout == ('a' * 2097152) + "\r\n" 11 | -------------------------------------------------------------------------------- /changelogs/fragments/win_shell-path.yml: -------------------------------------------------------------------------------- 1 | bugfixes: 2 | - >- 3 | win_shell - Ensure the default ``executable`` uses the absolute path to ``powershell.exe`` rather than looking it 4 | up in the ``PATH`` environment. 5 | 6 | minor_changes: 7 | - >- 8 | win_shell - Support using ``pwsh.exe`` as the executable in a mode similar to how ``powershell.exe`` is run. 9 | -------------------------------------------------------------------------------- /tests/integration/targets/win_acl/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | test_acl_path: '{{ remote_tmp_dir }}\win_acl .ÅÑŚÌβŁÈ [$!@^&test(;)]' 3 | test_acl_network_path: \\localhost\{{ test_acl_path[0:1] }}$\{{ test_acl_path[3:] }} 4 | # Use HKU as that path is not automatically loaded in the PSProvider making our test more complex 5 | test_acl_reg_path: HKU:\.DEFAULT\Ansible Test .ÅÑŚÌβŁÈ [$!@^&test(;)] -------------------------------------------------------------------------------- /tests/integration/targets/win_acl_inheritance/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | test_win_acl_inheritance_path: C:\ansible\win_acl_inheritance .ÅÑŚÌβŁÈ [$!@^&test(;)] 3 | test_win_acl_inheritance_network_path: \\localhost\{{ test_win_acl_inheritance_path[0:1] }}$\{{ test_win_acl_inheritance_path[3:] }} 4 | test_win_acl_inheritance_registry_path: HKU:\.DEFAULT\Ansible Test .ÅÑŚÌβŁÈ [$!@^&test(;)] 5 | -------------------------------------------------------------------------------- /.ansible-lint: -------------------------------------------------------------------------------- 1 | profile: production 2 | 3 | exclude_paths: 4 | # This file is autogenerated so we cannot change the format 5 | - changelogs/changelog.yaml 6 | # Incorrect error around supported ansible versions in this file 7 | - meta/runtime.yml 8 | - tests/integration/ 9 | # We skip a rule that has to be skipped 10 | - tests/sanity/ignore-*.txt 11 | - tests/unit/ 12 | -------------------------------------------------------------------------------- /tests/integration/targets/win_http_proxy/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: make sure we start the tests with no proxy set 3 | win_http_proxy: 4 | 5 | - block: 6 | - name: run tests 7 | include_tasks: tests.yml 8 | 9 | always: 10 | - name: remove any explicit proxy settings 11 | win_http_proxy: 12 | 13 | - name: reset WinINet proxy settings 14 | win_inet_proxy: 15 | -------------------------------------------------------------------------------- /.azure-pipelines/commands/sanity.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o pipefail -eux 4 | 5 | if [ "${BASE_BRANCH:-}" ]; then 6 | base_branch="origin/${BASE_BRANCH}" 7 | else 8 | base_branch="" 9 | fi 10 | 11 | # shellcheck disable=SC2086 12 | ansible-test sanity --color -v --junit ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} \ 13 | --docker --base-branch "${base_branch}" --allow-disabled 14 | -------------------------------------------------------------------------------- /tests/integration/targets/win_dns_zone/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Defines the test to run, possible values: 'standalone' or 'activedirectory' 3 | # 'standalone' installs a mock Windows DNS server and runs tests that only 4 | # include file backed DNS zones. 5 | # 'activedirectory' installs a mock AD/DNS server and runs tests that include 6 | # AD integrated and file backed DNS zones. 7 | win_dns_zone_test_type: standalone -------------------------------------------------------------------------------- /tests/integration/targets/win_product_facts/tasks/main.yml: -------------------------------------------------------------------------------- 1 | # This file is part of Ansible 2 | 3 | # Copyright: (c) 2017, Dag Wieers (dagwieers) 4 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 5 | 6 | - win_product_facts: 7 | 8 | - assert: 9 | that: 10 | - ansible_os_product_id is defined 11 | - ansible_os_product_key is defined 12 | -------------------------------------------------------------------------------- /tests/integration/targets/win_reboot/templates/post_reboot.ps1: -------------------------------------------------------------------------------- 1 | if (Test-Path -LiteralPath '{{remote_tmp_dir}}\win_reboot_test') { 2 | New-ItemProperty -LiteralPath 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager' ` 3 | -Name PendingFileRenameOperations ` 4 | -Value @("\??\{{remote_tmp_dir}}\win_reboot_test`0") ` 5 | -PropertyType MultiString 6 | Restart-Computer -Force 7 | exit 1 8 | } 9 | -------------------------------------------------------------------------------- /tests/integration/targets/win_service/files/Program.cs: -------------------------------------------------------------------------------- 1 | using System.ServiceProcess; 2 | 3 | namespace SleepService 4 | { 5 | internal static class Program 6 | { 7 | private static void Main(string[] args) 8 | { 9 | ServiceBase.Run(new ServiceBase[1] 10 | { 11 | (ServiceBase) new SleepService(args) 12 | }); 13 | } 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /tests/integration/targets/win_copy/files-different/vault/vault-file: -------------------------------------------------------------------------------- 1 | $ANSIBLE_VAULT;1.1;AES256 2 | 30353665333635633433356261616636356130386330363962386533303566313463383734373532 3 | 3933643234323638623939613462346361313431363939370a303532656338353035346661353965 4 | 34656231633238396361393131623834316262306533663838336362366137306562646561383766 5 | 6363373965633337640a373666336461613337346131353564383134326139616561393664663563 6 | 3431 7 | -------------------------------------------------------------------------------- /tests/integration/targets/win_dsc/files/xTestCompositeDsc/1.0.0/DSCResources/xTestComposite/xTestComposite.psd1: -------------------------------------------------------------------------------- 1 | @{ 2 | RootModule = 'xTestComposite.schema.psm1' 3 | ModuleVersion = '1.0.0' 4 | GUID = 'f488c0d7-31ae-49bd-b2e6-f72718fc4b34' 5 | Description = 'Example composite DSC Resource' 6 | FunctionsToExport = 'xTestComposite' 7 | PrivateData = @{ 8 | PSData = @{ 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/integration/targets/win_inet_proxy/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: make sure we start the tests with the defaults 3 | win_inet_proxy: 4 | 5 | - block: 6 | - name: run tests 7 | include_tasks: tests.yml 8 | 9 | always: 10 | - name: reset proxy back to defaults 11 | win_inet_proxy: 12 | 13 | - name: remove phonebook entry 14 | win_phonebook_entry: 15 | name: Ansible Test Dialup 16 | state: absent 17 | -------------------------------------------------------------------------------- /tests/integration/targets/win_mapped_drive/defaults/main.yml: -------------------------------------------------------------------------------- 1 | test_win_mapped_drive_letter: M 2 | test_win_mapped_drive_path: share1 3 | test_win_mapped_drive_path2: share2 4 | 5 | test_win_mapped_drive_local_path: C:\ansible\win_mapped_drive\share1 6 | test_win_mapped_drive_local_path2: C:\ansible\win_mapped_drive\share2 7 | 8 | test_win_mapped_drive_temp_user: TestMappedUser 9 | test_win_mapped_drive_temp_password: aZ293jgkdslgj4 10 | -------------------------------------------------------------------------------- /tests/integration/targets/win_dsc/files/xTestDsc/1.0.0/xTestDsc.psd1: -------------------------------------------------------------------------------- 1 | @{ 2 | ModuleVersion = '1.0.0' 3 | GUID = '80c895c4-de3f-4d6d-8fa4-c504c96b6f22' 4 | Author = 'Ansible' 5 | CompanyName = 'Ansible' 6 | Copyright = '(c) 2019' 7 | Description = 'Test DSC Resource for Ansible integration tests' 8 | PowerShellVersion = '5.0' 9 | CLRVersion = '4.0' 10 | FunctionsToExport = @() 11 | CmdletsToExport = @() 12 | } 13 | 14 | -------------------------------------------------------------------------------- /tests/integration/targets/win_dsc/files/xTestDsc/1.0.1/xTestDsc.psd1: -------------------------------------------------------------------------------- 1 | @{ 2 | ModuleVersion = '1.0.1' 3 | GUID = '80c895c4-de3f-4d6d-8fa4-c504c96b6f22' 4 | Author = 'Ansible' 5 | CompanyName = 'Ansible' 6 | Copyright = '(c) 2019' 7 | Description = 'Test DSC Resource for Ansible integration tests' 8 | PowerShellVersion = '5.0' 9 | CLRVersion = '4.0' 10 | FunctionsToExport = @() 11 | CmdletsToExport = @() 12 | } 13 | 14 | -------------------------------------------------------------------------------- /tests/integration/targets/module_utils_Process/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: run Process.cs tests 2 | process_cs_tests: 3 | register: process_cs_actual 4 | 5 | - assert: 6 | that: 7 | - process_cs_actual.data == 'success' 8 | 9 | - name: run Process.psm1 tests 10 | process_pwsh_tests: 11 | print_argv: '{{ win_printargv_path }}' 12 | register: process_pwsh_actual 13 | 14 | - assert: 15 | that: 16 | - process_pwsh_actual.data == 'success' 17 | -------------------------------------------------------------------------------- /tests/integration/targets/win_command/files/crt_setmode.c: -------------------------------------------------------------------------------- 1 | // crt_setmode.c 2 | // This program uses _setmode to change 3 | // stdout from text mode to binary mode. 4 | // Used to test output_encoding_override for win_command. 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | int main(void) 11 | { 12 | _setmode(_fileno(stdout), _O_BINARY); 13 | // Translates to 日本 in shift_jis 14 | printf("\x93\xFa\x96\x7B - Japan"); 15 | } 16 | -------------------------------------------------------------------------------- /tests/integration/targets/win_service/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | test_win_service_binary_url: https://ansible-ci-files.s3.amazonaws.com/test/integration/targets/win_service/SleepService.exe 3 | test_win_service_dir: C:\ansible testing\[win_service] 4 | test_win_service_path: '{{ test_win_service_dir }}\SleepService.exe' 5 | test_win_service_name: TestService [*abc] 6 | test_win_service_display_name: Test Service 7 | test_win_service_description: Test Service description 8 | -------------------------------------------------------------------------------- /.azure-pipelines/commands/lint.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o pipefail -eux 4 | 5 | # This is aligned with the galaxy-importer used by AH. 6 | # Check what galaxy_importer_version is used in the galaxy project at 7 | # https://galaxy.ansible.com/api/ 8 | 9 | # Then check the ansible-lint upper bound at 10 | # https://github.com/ansible/galaxy-importer/blob/v${VERSION}/setup.cfg 11 | 12 | python -m pip install \ 13 | 'ansible-lint==25.5.0' 14 | 15 | ansible-lint 16 | -------------------------------------------------------------------------------- /tests/integration/targets/win_dsc/files/xTestCompositeDsc/1.0.0/xTestCompositeDsc.psd1: -------------------------------------------------------------------------------- 1 | @{ 2 | RootModule = '' 3 | ModuleVersion = '1.0.0' 4 | GUID = '2650b3a8-f6c2-4dd9-a9de-55e5e6374a3e' 5 | Author = '' 6 | CompanyName = '' 7 | Copyright = '' 8 | Description = 'Example composite DSC Resource' 9 | PowerShellVersion = '5.1' 10 | DscResourcesToExport = 'xTestComposite' 11 | PrivateData = @{ 12 | PSData = @{ 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tests/integration/targets/win_copy/files-different/vault/folder/nested-vault-file: -------------------------------------------------------------------------------- 1 | $ANSIBLE_VAULT;1.1;AES256 2 | 65653164323866373138353632323531393664393563633665373635623763353561386431373366 3 | 3232353263363034313136663062623336663463373966320a333763323032646463386432626161 4 | 36386330356637666362396661653935653064623038333031653335626164376465353235303636 5 | 3335616231663838620a303632343938326538656233393562303162343261383465623261646664 6 | 33613932343461626339333832363930303962633364303736376634396364643861 7 | -------------------------------------------------------------------------------- /tests/integration/targets/win_service_info/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | test_path: '{{ remote_tmp_dir }}\win_service_info .ÅÑŚÌβŁÈ [$!@^&test(;)]' 3 | service_url: https://ansible-ci-files.s3.amazonaws.com/test/integration/targets/win_service/SleepService.exe 4 | 5 | service_name1: ansible_service_info_test [*abc] 6 | service_name2: ansible_service_info_test2 7 | service_name3: ansible_service_info_other 8 | service_names: 9 | - '{{ service_name1 }}' 10 | - '{{ service_name2 }}' 11 | - '{{ service_name3 }}' 12 | -------------------------------------------------------------------------------- /tests/integration/targets/win_hostname/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: get the current hostname 3 | win_command: hostname 4 | register: current_hostname 5 | 6 | - block: 7 | - name: run tests 8 | include_tasks: test.yml 9 | 10 | always: 11 | - name: reset the hostname back to the original 12 | win_hostname: 13 | name: '{{current_hostname.stdout_lines[0]}}' 14 | register: reset_hostname 15 | 16 | - name: reboot if required 17 | win_reboot: 18 | when: reset_hostname.reboot_required 19 | -------------------------------------------------------------------------------- /tests/integration/targets/win_package/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: remove trusted root cert 3 | win_certificate_store: 4 | thumbprint: '{{ test_win_package_msix_packages.thumbprint }}' 5 | store_location: LocalMachine 6 | store_name: Root 7 | state: absent 8 | 9 | - name: remove sideloading mode for msix 10 | win_regedit: 11 | path: HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock 12 | name: AllowAllTrustedApps 13 | data: 0 14 | type: dword 15 | state: present 16 | -------------------------------------------------------------------------------- /meta/runtime.yml: -------------------------------------------------------------------------------- 1 | requires_ansible: ">=2.16.0" 2 | plugin_routing: 3 | modules: 4 | win_domain_controller: 5 | tombstone: 6 | removal_version: 3.0.0 7 | warning_text: Use microsoft.ad.domain_controller instead. 8 | win_domain_membership: 9 | tombstone: 10 | removal_version: 3.0.0 11 | warning_text: Use microsoft.ad.membership instead. 12 | win_domain: 13 | tombstone: 14 | removal_version: 3.0.0 15 | warning_text: Use microsoft.ad.domain instead. 16 | -------------------------------------------------------------------------------- /tests/integration/targets/win_timezone/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: get current timezone 2 | win_command: tzutil.exe /g 3 | register: original_timezone 4 | changed_when: false 5 | 6 | - block: 7 | - name: Change starting timezone to GMT for test baseline 8 | win_timezone: 9 | timezone: GMT Standard Time 10 | 11 | - name: run tests 12 | import_tasks: tests.yml 13 | 14 | always: 15 | - name: reset timezone back to defaults 16 | win_timezone: 17 | timezone: "{{ original_timezone.stdout | trim }}" 18 | -------------------------------------------------------------------------------- /tests/integration/targets/win_hosts/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: take a copy of the original hosts file 3 | ansible.windows.win_copy: 4 | src: C:\Windows\System32\drivers\etc\hosts 5 | dest: '{{ remote_tmp_dir }}\hosts' 6 | remote_src: yes 7 | 8 | - block: 9 | - name: run tests 10 | include_tasks: tests.yml 11 | 12 | always: 13 | - name: restore hosts file 14 | ansible.windows.win_copy: 15 | src: '{{ remote_tmp_dir }}\hosts' 16 | dest: C:\Windows\System32\drivers\etc\hosts 17 | remote_src: yes 18 | -------------------------------------------------------------------------------- /tests/integration/targets/win_user/files/lockout_user.ps1: -------------------------------------------------------------------------------- 1 | trap { 2 | Write-Error -ErrorRecord $_ 3 | exit 1 4 | } 5 | 6 | $username = $args[0] 7 | [void][system.reflection.assembly]::LoadWithPartialName('System.DirectoryServices.AccountManagement') 8 | $pc = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext 'Machine', $env:COMPUTERNAME 9 | For ($i = 1; $i -le 10; $i++) { 10 | try { 11 | $null = $pc.ValidateCredentials($username, 'b@DP@ssw0rd') 12 | } 13 | catch { 14 | break 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tests/integration/targets/win_package/files/bad.wsx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /plugins/modules/win_ping.ps1: -------------------------------------------------------------------------------- 1 | #!powershell 2 | 3 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | 5 | #AnsibleRequires -CSharpUtil Ansible.Basic 6 | 7 | $spec = @{ 8 | options = @{ 9 | data = @{ type = "str"; default = "pong" } 10 | } 11 | supports_check_mode = $true 12 | } 13 | $module = [Ansible.Basic.AnsibleModule]::Create($args, $spec) 14 | $data = $module.Params.data 15 | 16 | if ($data -eq "crash") { 17 | throw "boom" 18 | } 19 | 20 | $module.Result.ping = $data 21 | $module.ExitJson() 22 | -------------------------------------------------------------------------------- /tests/integration/targets/win_regedit/tasks/cleanup.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: load HKLM:\ANSIBLE with test hive 3 | win_command: reg.exe load HKLM\ANSIBLE C:\Users\Default\NTUSER.dat 4 | failed_when: false 5 | 6 | - name: make sure testing keys are removed before test 7 | win_regedit: 8 | path: '{{item}}' 9 | delete_key: yes 10 | state: absent 11 | with_items: 12 | - '{{test_win_regedit_local_key}}' 13 | - '{{test_win_regedit_classes_key}}' 14 | - '{{test_win_regedit_hive_key}}' 15 | 16 | - name: ensure HKLM:\ANSIBLE is unloaded 17 | win_command: reg.exe unload HKLM\ANSIBLE 18 | failed_when: false 19 | -------------------------------------------------------------------------------- /tests/integration/targets/win_environment/tasks/cleanup.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: ensure test environment value is not set in all scope 3 | win_environment: 4 | name: "{{test_environment_name}}" 5 | state: absent 6 | level: "{{item}}" 7 | with_items: 8 | - machine 9 | - process 10 | - user 11 | 12 | - name: ensure test multi environment vars are not set in all scope 13 | win_environment: 14 | name: "{{ item.0.key }}" 15 | state: absent 16 | level: "{{ item.1 }}" 17 | with_nested: 18 | - "{{ test_multi_value_with_removal_environment_values | dict2items }}" 19 | - [ 'machine', 'process', 'user' ] 20 | -------------------------------------------------------------------------------- /tests/integration/targets/win_dsc/files/xTestClassDsc/1.0.0/xTestClassDsc.psd1: -------------------------------------------------------------------------------- 1 | @{ 2 | RootModule = 'xTestClassDsc.psm1' 3 | ModuleVersion = '1.0.0' 4 | GUID = '883aa273-27b8-4b9f-a96d-6e4056f987b2' 5 | Author = '' 6 | CompanyName = '' 7 | Copyright = '' 8 | Description = 'Example DSC Resource' 9 | PowerShellVersion = '5.1' 10 | RequiredAssemblies = @("System.ServiceProcess") 11 | FunctionsToExport = '*' 12 | CmdletsToExport = '*' 13 | VariablesToExport = '*' 14 | AliasesToExport = '*' 15 | DscResourcesToExport = 'xTestClassDsc' 16 | PrivateData = @{ 17 | PSData = @{ 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | name: Stale pull request handler 2 | "on": 3 | schedule: 4 | - cron: 0 0 * * * 5 | 6 | permissions: 7 | pull-requests: write 8 | 9 | jobs: 10 | stale: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/stale@v4.0.0 15 | id: stale 16 | with: 17 | days-before-stale: -1 18 | days-before-pr-stale: 28 19 | days-before-pr-close: 14 20 | stale-pr-label: stale 21 | stale-pr-message: >- 22 | This pull request is stale because it has been open for 4 weeks with no activity. 23 | Remove stale label or comment or this will be closed in 2 weeks. 24 | -------------------------------------------------------------------------------- /tests/integration/targets/win_audit_rule/defaults/main.yml: -------------------------------------------------------------------------------- 1 | test_audit_rule_directory: c:\windows\temp\{{ 'ansible test win_audit_policy' | to_uuid }} 2 | test_audit_rule_file: c:\windows\temp\{{ 'ansible test win_audit_policy' | to_uuid }}.txt 3 | test_audit_rule_registry: HKCU:\{{ 'ansible test win_audit_policy' | to_uuid }} 4 | test_audit_rule_rights1: 'Delete' 5 | test_audit_rule_rights2: 'Delete,ChangePermissions' 6 | test_audit_rule_rights3: 'Delete,Read' 7 | test_audit_rule_user1: 'everyone' 8 | test_audit_rule_user2: 'Administrator' 9 | test_audit_rule_audit_flags: success 10 | test_audit_rule_propagation_flag: NoPropagateInherit 11 | test_audit_rule_inheritance_flags: ContainerInherit -------------------------------------------------------------------------------- /tests/integration/targets/win_dns_record/tasks/main.yml: -------------------------------------------------------------------------------- 1 | # We do an explicit OS version check here *INSTEAD OF* the usual test for 2 | # cmdlet existence. That's because a cmdlet test here won't work without first 3 | # installing the DNS feature, but we don't want to install the feature on OS' 4 | # that can't be supported anyway. Hence this fallback to an explicit OS version 5 | # test. 6 | - name: check OS version is supported 7 | ansible.windows.win_shell: 'if ([Environment]::OSVersion.Version -ge [Version]"6.2") { $true } else { $false }' 8 | register: os_supported 9 | 10 | - name: run tests on supported hosts 11 | import_tasks: tests.yml 12 | when: os_supported.stdout | trim | bool 13 | -------------------------------------------------------------------------------- /tests/integration/targets/win_environment/defaults/main.yml: -------------------------------------------------------------------------------- 1 | test_environment_name: TEST_VALUE 2 | test_machine_environment_value: "%SystemRoot%\\System32" 3 | test_new_machine_environment_value: C:\Windows\System32 4 | test_user_environment_value: C:\Program Files 5 | test_new_user_environment_value: C:\Program Files (x86) 6 | 7 | test_multi_value_environment_values: 8 | TEST_VAR_A: value A 9 | TEST_VAR_B: value B 10 | 11 | test_removal_var_name: TEST_VAR_C 12 | test_removal_var_dict: "{{ 13 | { test_removal_var_name: '' } 14 | }}" 15 | 16 | test_multi_value_with_removal_environment_values: "{{ 17 | test_multi_value_environment_values 18 | | combine(test_removal_var_dict) 19 | }}" 20 | -------------------------------------------------------------------------------- /.azure-pipelines/scripts/time-command.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Prepends a relative timestamp to each input line from stdin and writes it to stdout.""" 3 | 4 | from __future__ import annotations 5 | 6 | import sys 7 | import time 8 | 9 | 10 | def main(): 11 | """Main program entry point.""" 12 | start = time.time() 13 | 14 | sys.stdin.reconfigure(errors='surrogateescape') 15 | sys.stdout.reconfigure(errors='surrogateescape') 16 | 17 | for line in sys.stdin: 18 | seconds = time.time() - start 19 | sys.stdout.write('%02d:%02d %s' % (seconds // 60, seconds % 60, line)) 20 | sys.stdout.flush() 21 | 22 | 23 | if __name__ == '__main__': 24 | main() 25 | -------------------------------------------------------------------------------- /tests/integration/targets/win_reg_stat/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: get value of expand string %windir% 3 | win_command: powershell.exe $env:windir 4 | register: win_dir_value 5 | 6 | - name: template out test registry structure 7 | win_template: 8 | src: test_reg.reg.j2 9 | dest: '{{ remote_tmp_dir }}\test_reg.reg' 10 | 11 | - name: import test registry structure 12 | win_command: reg.exe import "{{ remote_tmp_dir }}\test_reg.reg" 13 | 14 | - block: 15 | - name: run tests 16 | import_tasks: tests.yml 17 | 18 | always: 19 | - name: remove test registry key 20 | win_regedit: 21 | path: HKCU:\{{ test_reg_path }} 22 | state: absent 23 | delete_key: True 24 | -------------------------------------------------------------------------------- /tests/integration/targets/win_share/defaults/main.yml: -------------------------------------------------------------------------------- 1 | test_win_share: true 2 | test_win_share_description: description 3 | test_win_share_path: C:\ansible\win_share 4 | test_win_share_name: test share 5 | 6 | # Cluster Test Params 7 | # Note: Disabled by default, set test_win_share_cluster to true 8 | # and add cluster_path / cluster_name vars (in your integration_config.yml 9 | # for example). The test instance must be a properly configured failover 10 | # cluster with at least one role and one cluster shared disk. 11 | test_win_share_cluster: false 12 | test_win_share_cluster_name: testcluster 13 | test_win_share_cluster_path: "{{ cluster_path }}" 14 | test_win_share_cluster_scope: "{{ cluster_name }}" 15 | -------------------------------------------------------------------------------- /tests/integration/targets/win_wait_for/files/http-server.ps1: -------------------------------------------------------------------------------- 1 | $ErrorActionPreference = 'Stop' 2 | 3 | $port = [int]$args[0] 4 | 5 | $endpoint = New-Object -TypeName System.Net.IPEndPoint([System.Net.IPAddress]::Parse("0.0.0.0"), $port) 6 | $listener = New-Object -TypeName System.Net.Sockets.TcpListener($endpoint) 7 | $listener.Server.ReceiveTimeout = 3000 8 | $listener.Start() 9 | 10 | try { 11 | while ($true) { 12 | if (-not $listener.Pending()) { 13 | Start-Sleep -Seconds 1 14 | } 15 | else { 16 | $client = $listener.AcceptTcpClient() 17 | $client.Close() 18 | break 19 | } 20 | } 21 | } 22 | finally { 23 | $listener.Stop() 24 | } 25 | -------------------------------------------------------------------------------- /galaxy.yml: -------------------------------------------------------------------------------- 1 | namespace: ansible 2 | name: windows 3 | version: 3.3.0 4 | readme: README.md 5 | authors: 6 | - Jordan Borean @jborean93 7 | - Matt Davis @nitzmahone 8 | description: | 9 | Ansible collection for core Windows plugins. 10 | license_file: COPYING 11 | tags: 12 | - windows 13 | dependencies: {} 14 | repository: https://github.com/ansible-collections/ansible.windows 15 | documentation: https://docs.ansible.com/ansible/devel/collections/ansible/windows 16 | homepage: https://github.com/ansible-collections/ansible.windows 17 | issues: https://github.com/ansible-collections/ansible.windows/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc 18 | build_ignore: 19 | - .vscode 20 | - tests/integration/inventory* 21 | - changelogs/.plugin-cache.yaml 22 | -------------------------------------------------------------------------------- /tests/integration/targets/setup_win_printargv/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: copy PrintArgv.cs to remote host 2 | win_copy: 3 | src: PrintArgv.cs 4 | dest: '{{ remote_tmp_dir }}\PrintArgv.cs' 5 | 6 | - name: compile PrintArgv.cs 7 | win_shell: | 8 | $ErrorActionPreference = 'Stop' 9 | $addParams = @{ 10 | TypeDefinition = (Get-Content -LiteralPath '{{ remote_tmp_dir }}\PrintArgv.cs' -Raw) 11 | OutputType = 'ConsoleApplication' 12 | OutputAssembly = '{{ remote_tmp_dir }}\PrintArgv.exe' 13 | ReferencedAssemblies = @('System.Web.Extensions.dll') 14 | } 15 | Add-Type @addParams 16 | 17 | - name: set fact containing PrintArgv binary path 18 | set_fact: 19 | win_printargv_path: '{{ remote_tmp_dir }}\PrintArgv.exe' 20 | -------------------------------------------------------------------------------- /tests/integration/targets/win_dns_record/tasks/clean.yml: -------------------------------------------------------------------------------- 1 | - name: Remove test zone, if present 2 | ansible.windows.win_shell: | 3 | $zone = '{{ item }}' 4 | $fail_on_missing = '{{ fail_on_missing | default(true) }}' 5 | 6 | Trap { If (-not $fail_on_missing) { continue } } 7 | Remove-DnsServerZone -Name $zone -Force 8 | 9 | # win_file could also do this, but it would need to know where the 10 | # SystemRoot is located via fact gathering, which we cannot assume. 11 | Trap { If (-not $fail_on_missing) { continue } } 12 | Remove-Item -Path $env:SystemRoot\system32\dns\$zone.dns 13 | 14 | $true # so pipeline exits cleanly if an error was ignored above 15 | loop: 16 | - '{{ win_dns_record_zone }}' 17 | - '{{ win_dns_record_revzone }}' 18 | -------------------------------------------------------------------------------- /tests/integration/targets/win_get_url/templates/slimftpd.conf.tmpl: -------------------------------------------------------------------------------- 1 | # http://www.wiki.uniformserver.com/index.php/SlimFTPd:_Config_File 2 | BindInterface Local 3 | BindPort 21 4 | CommandTimeout 300 5 | ConnectTimeout 15 6 | MaxConnections 20 7 | LookupHosts On 8 | 9 | 10 | Password "" 11 | Mount / "{{ slimftpd_link | replace('\\', '\\\\') }}\\ftp" 12 | Allow /anon All 13 | Deny /user All 14 | Deny /user-pass All 15 | 16 | 17 | 18 | Mount / "{{ slimftpd_link | replace('\\', '\\\\') }}\\ftp" 19 | Allow /anon All 20 | Allow /user All 21 | Deny /user-pass All 22 | 23 | 24 | 25 | Password "password" 26 | Mount / "{{ slimftpd_link | replace('\\', '\\\\') }}\\ftp" 27 | Allow / All 28 | 29 | -------------------------------------------------------------------------------- /tests/integration/targets/win_dsc/files/xTestCompositeDsc/1.0.0/DSCResources/xTestComposite/xTestComposite.schema.psm1: -------------------------------------------------------------------------------- 1 | Configuration xTestComposite { 2 | param 3 | ( 4 | [string]$TestValue = 'test' 5 | ) 6 | 7 | Import-DSCResource -ModuleName 'PSDesiredStateConfiguration' 8 | 9 | Registry "first setting" { 10 | Key = 'HKLM:\Software\Microsoft\Windows NT\CurrentVersion\Winlogon' 11 | ValueData = $TestValue 12 | ValueName = 'DoesntMatter' 13 | ValueType = 'String' 14 | } 15 | 16 | Registry "second setting" { 17 | Key = 'HKLM:\Software\Microsoft\Windows NT\CurrentVersion\Winlogon' 18 | ValueData = $TestValue 19 | ValueName = 'AlsoDoesntMatter' 20 | ValueType = 'String' 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/integration/targets/win_user_right/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Get current entries for right 3 | test_get_right: 4 | name: '{{ test_win_user_right_name }}' 5 | register: actual_users 6 | 7 | - name: Get facts 8 | ansible.builtin.setup: 9 | 10 | - name: Ensure rights 11 | block: 12 | - name: Ensure right is empty before test 13 | ansible.windows.win_user_right: 14 | name: '{{ test_win_user_right_name }}' 15 | users: [] 16 | action: set 17 | 18 | - name: Run tests 19 | ansible.builtin.include_tasks: tests.yml 20 | 21 | always: 22 | - name: Reset entries for test right 23 | ansible.windows.win_user_right: 24 | name: '{{ test_win_user_right_name }}' 25 | users: '{{ actual_users.users }}' 26 | action: set 27 | -------------------------------------------------------------------------------- /tests/integration/targets/win_dsc/files/xTestClassDsc/1.0.0/xTestClassDsc.psm1: -------------------------------------------------------------------------------- 1 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSDSCDscExamplesPresent", "")] 2 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSDSCDscTestsPresent", "")] 3 | param() 4 | 5 | enum Ensure { 6 | Absent 7 | Present 8 | } 9 | 10 | [DscResource()] 11 | class xTestClassDsc { 12 | [DscProperty(Key)] 13 | [Ensure]$Ensure 14 | 15 | [xTestClassDsc] Get() { 16 | return $this 17 | } 18 | 19 | [bool] Test() { 20 | return $true 21 | } 22 | 23 | [void] Set() { 24 | [System.ServiceProcess.ServiceControllerStatus] $stopped = [System.ServiceProcess.ServiceControllerStatus]::Stopped 25 | if (-not $stopped) { 26 | throw "test" 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tests/integration/targets/async_status/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: run async task 2 | win_ping: 3 | async: 30 4 | poll: 2 5 | register: async_res 6 | 7 | - name: assert run async task 8 | assert: 9 | that: 10 | - async_res is finished 11 | - async_res is successful 12 | - async_res.ping == 'pong' 13 | 14 | - name: check mode support was added in ansible 2.18 15 | when: ansible_version.full is version('2.18', '>=') 16 | block: 17 | - name: run async task - check mode 18 | win_ping: 19 | async: 30 20 | poll: 2 21 | register: async_res_check 22 | check_mode: true 23 | 24 | - name: assert run async task - check mode 25 | assert: 26 | that: 27 | - async_res_check is finished 28 | - async_res_check is successful 29 | - async_res_check.ping == 'pong' 30 | -------------------------------------------------------------------------------- /.azure-pipelines/scripts/process-results.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Check the test results and set variables for use in later steps. 3 | 4 | set -o pipefail -eu 5 | 6 | if [[ "$PWD" =~ /ansible_collections/ ]]; then 7 | output_path="tests/output" 8 | else 9 | output_path="test/results" 10 | fi 11 | 12 | echo "##vso[task.setVariable variable=outputPath]${output_path}" 13 | 14 | if compgen -G "${output_path}"'/junit/*.xml' > /dev/null; then 15 | echo "##vso[task.setVariable variable=haveTestResults]true" 16 | fi 17 | 18 | if compgen -G "${output_path}"'/bot/ansible-test-*' > /dev/null; then 19 | echo "##vso[task.setVariable variable=haveBotResults]true" 20 | fi 21 | 22 | if compgen -G "${output_path}"'/coverage/*' > /dev/null; then 23 | echo "##vso[task.setVariable variable=haveCoverageData]true" 24 | fi 25 | -------------------------------------------------------------------------------- /.azure-pipelines/scripts/aggregate-coverage.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Aggregate code coverage results for later processing. 3 | 4 | set -o pipefail -eu 5 | 6 | agent_temp_directory="$1" 7 | 8 | PATH="${PWD}/bin:${PATH}" 9 | 10 | mkdir "${agent_temp_directory}/coverage/" 11 | 12 | options=(--venv --venv-system-site-packages --color -v) 13 | 14 | ansible-test coverage combine --export "${agent_temp_directory}/coverage/" "${options[@]}" 15 | 16 | if ansible-test coverage analyze targets generate --help >/dev/null 2>&1; then 17 | # Only analyze coverage if the installed version of ansible-test supports it. 18 | # Doing so allows this script to work unmodified for multiple Ansible versions. 19 | ansible-test coverage analyze targets generate "${agent_temp_directory}/coverage/coverage-analyze-targets.json" "${options[@]}" 20 | fi 21 | -------------------------------------------------------------------------------- /.azure-pipelines/commands/windows.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o pipefail -eux 4 | 5 | declare -a args 6 | IFS='/:' read -ra args <<< "$1" 7 | 8 | version="${args[1]}" 9 | connection="${args[2]}" 10 | connection_setting="${args[3]}" 11 | 12 | if [ "${#args[0]}" -gt 4 ]; then 13 | target="shippable/windows/group${args[4]}/" 14 | else 15 | target="shippable/windows/" 16 | fi 17 | 18 | stage="${S:-prod}" 19 | provider="${P:-default}" 20 | 21 | # shellcheck disable=SC2086 22 | ansible-test windows-integration --color -v --retry-on-error "${target}" ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} ${UNSTABLE:+"$UNSTABLE"} \ 23 | --controller "docker:default" \ 24 | --target "remote:windows/${version},connection=${connection}+${connection_setting},provider=${provider}" \ 25 | --remote-terminate always --remote-stage "${stage}" 26 | -------------------------------------------------------------------------------- /plugins/modules/slurp.ps1: -------------------------------------------------------------------------------- 1 | #!powershell 2 | 3 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | 5 | #Requires -Module Ansible.ModuleUtils.Legacy 6 | 7 | $params = Parse-Args $args -supports_check_mode $true 8 | $src = Get-AnsibleParam -obj $params -name "src" -type "path" -aliases "path" -failifempty $true 9 | 10 | $result = @{ 11 | changed = $false 12 | } 13 | 14 | If (Test-Path -LiteralPath $src -PathType Leaf) { 15 | $bytes = [System.IO.File]::ReadAllBytes($src) 16 | $result.content = [System.Convert]::ToBase64String($bytes) 17 | $result.encoding = "base64" 18 | Exit-Json $result 19 | } 20 | ElseIf (Test-Path -LiteralPath $src -PathType Container) { 21 | Fail-Json $result "Path $src is a directory" 22 | } 23 | Else { 24 | Fail-Json $result "Path $src is not found" 25 | } 26 | -------------------------------------------------------------------------------- /tests/integration/targets/win_user/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: create test group that has a network logon denied 3 | win_group: 4 | name: win_user-test 5 | state: present 6 | 7 | - name: add test group to SeDenyNetworkLogonRight 8 | win_user_right: 9 | name: SeDenyNetworkLogonRight 10 | users: 11 | - win_user-test 12 | action: add 13 | 14 | - block: 15 | - name: run tests 16 | include_tasks: tests.yml 17 | 18 | always: 19 | - name: remove SeDenyNetworkLogonRight on test group 20 | win_user_right: 21 | name: SeDenyNetworkLogonRight 22 | users: 23 | - win_user-test 24 | action: remove 25 | 26 | - name: remove test group 27 | win_group: 28 | name: win_user-test 29 | state: absent 30 | 31 | - name: remove the test user 32 | win_user: 33 | name: '{{ test_win_user_name }}' 34 | state: absent 35 | -------------------------------------------------------------------------------- /changelogs/config.yaml: -------------------------------------------------------------------------------- 1 | changelog_filename_template: ../CHANGELOG.rst 2 | changelog_filename_version_depth: 0 3 | changes_file: changelog.yaml 4 | changes_format: combined 5 | keep_fragments: false 6 | mention_ancestor: true 7 | new_plugins_after_name: removed_features 8 | notesdir: fragments 9 | prelude_section_name: release_summary 10 | prelude_section_title: Release Summary 11 | sections: 12 | - - major_changes 13 | - Major Changes 14 | - - minor_changes 15 | - Minor Changes 16 | - - breaking_changes 17 | - Breaking Changes / Porting Guide 18 | - - deprecated_features 19 | - Deprecated Features 20 | - - removed_features 21 | - Removed Features (previously deprecated) 22 | - - security_fixes 23 | - Security Fixes 24 | - - bugfixes 25 | - Bugfixes 26 | - - known_issues 27 | - Known Issues 28 | title: Ansible Windows 29 | trivial_section_name: trivial 30 | -------------------------------------------------------------------------------- /tests/unit/plugins/action/test_win_copy.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright: Contributors to the Ansible project 3 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | 5 | from ansible_collections.ansible.windows.plugins.action import win_copy 6 | 7 | 8 | def test_walk_dirs_with_symlink(mocker): 9 | mocker.patch("os.path.islink", return_value=True) 10 | mocker.patch("os.readlink", return_value="/path/to/real/file.txt") 11 | mocker.patch("os.path.basename", return_value="file.txt") 12 | 13 | ret = win_copy._walk_dirs("/path/to/symlink", loader=None, local_follow=False) 14 | expected = { 15 | "directories": [], 16 | "files": [], 17 | "symlinks": [ 18 | { 19 | "dest": "file.txt", 20 | "src": "/path/to/real/file.txt", 21 | } 22 | ], 23 | } 24 | assert ret == expected 25 | -------------------------------------------------------------------------------- /tests/integration/targets/win_group/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - block: 2 | - name: remove test group before test 3 | win_group: 4 | name: '{{ test_win_group_name }}' 5 | state: absent 6 | 7 | - name: create test users 8 | win_user: 9 | name: '{{ item }}' 10 | state: present 11 | password: 7a4e3943-3f80-4b6b-baed-408c2d763c8f 12 | register: test_users 13 | loop: 14 | - LocalUser1 15 | - LocalUser2 16 | - LocalUser3 17 | 18 | - name: run tests 19 | import_tasks: tests.yml 20 | 21 | - name: run membership tests 22 | import_tasks: members.yml 23 | 24 | always: 25 | - name: remove test group after test 26 | win_group: 27 | name: '{{ test_win_group_name }}' 28 | state: absent 29 | 30 | - name: remove test users after test 31 | win_user: 32 | name: '{{ item.name }}' 33 | state: absent 34 | loop: '{{ test_users.results | default([]) }}' 35 | -------------------------------------------------------------------------------- /tests/integration/targets/setup_win_device/tasks/main.yml: -------------------------------------------------------------------------------- 1 | # Creates a network adapter device for testing purposes and registers the following vars 2 | # network_device_name: The name of the network device 3 | # network_adapter_name: The name of the network adapter 4 | --- 5 | - name: create dummy network adapter device 6 | win_device: 7 | path: '%WinDir%\Inf\netloop.inf' 8 | hardware_id: '*msloop' 9 | state: present 10 | register: network_device_name_raw 11 | notify: remove dummy network adapter device 12 | 13 | - set_fact: 14 | network_device_name: '{{ network_device_name_raw.name }}' 15 | 16 | - name: get name of the dummy network adapter 17 | win_shell: (Get-CimInstance -Class Win32_NetworkAdapter -Filter "Name='{{ network_device_name }}'").NetConnectionID 18 | changed_when: False 19 | register: network_adapter_name_raw 20 | 21 | - set_fact: 22 | network_adapter_name: '{{ network_adapter_name_raw.stdout | trim }}' 23 | -------------------------------------------------------------------------------- /tests/integration/targets/win_dhcp_lease/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - block: 3 | - name: Check DHCP Service/Role Install State 4 | ansible.windows.win_feature: 5 | name: DHCP 6 | state: present 7 | include_management_tools: yes 8 | register: dhcp_role 9 | 10 | - name: Reboot if Necessary 11 | ansible.windows.win_reboot: 12 | when: dhcp_role.reboot_required 13 | 14 | - name: Add the DHCP scope 15 | ansible.windows.win_shell: | 16 | Add-DhcpServerv4Scope -Name "TestNetwork" -StartRange {{ dhcp_scope_start }} -EndRange {{dhcp_scope_end }} -SubnetMask {{ dhcp_scope_subnet_mask }} 17 | 18 | - name: Run tests without check mode 19 | include_tasks: tests.yml 20 | 21 | - name: Run tests in check mode 22 | include_tasks: tests_checkmode.yml 23 | 24 | always: 25 | - name: Remove the DHCP scope 26 | ansible.windows.win_shell: | 27 | Remove-DhcpServerv4Scope -ScopeId {{ dhcp_scope_id }} -Force -------------------------------------------------------------------------------- /.azure-pipelines/scripts/run-tests.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Configure the test environment and run the tests. 3 | 4 | set -o pipefail -eu 5 | 6 | entry_point="$1" 7 | test="$2" 8 | read -r -a coverage_branches <<< "$3" # space separated list of branches to run code coverage on for scheduled builds 9 | 10 | export COMMIT_MESSAGE 11 | export COMPLETE 12 | export COVERAGE 13 | export IS_PULL_REQUEST 14 | 15 | if [ "${SYSTEM_PULLREQUEST_TARGETBRANCH:-}" ]; then 16 | IS_PULL_REQUEST=true 17 | COMMIT_MESSAGE=$(git log --format=%B -n 1 HEAD^2) 18 | else 19 | IS_PULL_REQUEST= 20 | COMMIT_MESSAGE=$(git log --format=%B -n 1 HEAD) 21 | fi 22 | 23 | COMPLETE= 24 | COVERAGE= 25 | 26 | if [ "${BUILD_REASON}" = "Schedule" ]; then 27 | COMPLETE=yes 28 | 29 | if printf '%s\n' "${coverage_branches[@]}" | grep -q "^${BUILD_SOURCEBRANCHNAME}$"; then 30 | COVERAGE=yes 31 | fi 32 | fi 33 | 34 | "${entry_point}" "${test}" 2>&1 | "$(dirname "$0")/time-command.py" 35 | -------------------------------------------------------------------------------- /tests/integration/targets/win_audit_policy_system/tasks/main.yml: -------------------------------------------------------------------------------- 1 | #turn off so then we can test changes occur on enable. Turning off for object access also 2 | #covers our subcategory test for file system 3 | - name: turn off auditing for category 4 | win_audit_policy_system: 5 | category: "{{ category_name }}" 6 | audit_type: [none] 7 | 8 | - name: turn off auditing for subcategory 9 | win_audit_policy_system: 10 | subcategory: "{{ subcategory_name }}" 11 | audit_type: none 12 | 13 | - block: 14 | - include_tasks: add.yml 15 | - include_tasks: modify.yml 16 | - include_tasks: remove.yml 17 | always: 18 | - name: CLEANUP turn "{{ category_name }}" back to no auditing 19 | win_audit_policy_system: 20 | category: "{{ category_name }}" 21 | audit_type: none 22 | 23 | - name: CLEANUP turn "{{ subcategory_name }}" back to no auditing 24 | win_audit_policy_system: 25 | subcategory: "{{ subcategory_name }}" 26 | audit_type: none 27 | -------------------------------------------------------------------------------- /tests/integration/targets/win_credential/defaults/main.yml: -------------------------------------------------------------------------------- 1 | # The certificate in files/cert.pfx was generated with the following commands 2 | # 3 | # cat > client.cnf < cmdInfo = new Dictionary() 19 | { 20 | {"command_line", cmdLine }, 21 | {"args", args}, 22 | }; 23 | 24 | JavaScriptSerializer jss = new JavaScriptSerializer(); 25 | jss.MaxJsonLength = int.MaxValue; 26 | jss.RecursionLimit = int.MaxValue; 27 | Console.WriteLine(jss.Serialize(cmdInfo)); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/integration/targets/win_stat/library/test_symlink_file.ps1: -------------------------------------------------------------------------------- 1 | #!powershell 2 | 3 | #Requires -Module Ansible.ModuleUtils.Legacy 4 | #Requires -Module Ansible.ModuleUtils.LinkUtil 5 | 6 | $params = Parse-Args $args 7 | 8 | $state = Get-AnsibleParam -obj $params -name "state" -type "str" -default "present" -validateset "absent", "present" 9 | $src = Get-AnsibleParam -obj $params -name "src" -type "path" -failifempty $true 10 | $target = Get-AnsibleParam -obj $params -name "target" -type "path" -failifempty $($state -eq "present") 11 | 12 | $result = @{ 13 | changed = $false 14 | } 15 | 16 | if ($state -eq "absent") { 17 | if (Test-Path -LiteralPath $src) { 18 | Load-LinkUtils 19 | Remove-Link -link_path $src 20 | $result.changed = $true 21 | } 22 | } 23 | else { 24 | if (-not (Test-Path -LiteralPath $src)) { 25 | Load-LinkUtils 26 | New-Link -link_path $src -link_target $target -link_type "link" 27 | $result.changed = $true 28 | } 29 | } 30 | 31 | Exit-Json -obj $result 32 | -------------------------------------------------------------------------------- /tests/integration/targets/win_hotfix/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # these hotfixes, are for Hyper-V, there may be a chance the system already has them 3 | # but in most cases for our CI purposes they wouldn't be present 4 | test_win_hotfix_good_url: https://ansible-ci-files.s3.amazonaws.com/test/integration/targets/win_hotfix/windows8.1-kb3027108-v2-x64_66366c7be2d64d83b63cac42bc40c0a3c01bc70d.msu 5 | test_win_hotfix_reboot_url: https://ansible-ci-files.s3.amazonaws.com/test/integration/targets/win_hotfix/windows8.1-kb2913659-v2-x64_963a4d890c9ff9cc83a97cf54305de6451038ba4.msu 6 | test_win_hotfix_bad_url: https://ansible-ci-files.s3.amazonaws.com/test/integration/targets/win_hotfix/windows8-rt-kb3172729-x64_69cab4c7785b1faa3fc450f32bed4873d53bb96f.msu 7 | test_win_hotfix_path: C:\ansible\win_hotfix 8 | 9 | test_win_hotfix_kb: KB3027108 10 | test_win_hotfix_identifier: Package_for_KB3027108~31bf3856ad364e35~amd64~~6.3.2.0 11 | 12 | test_win_hotfix_reboot_kb: KB2913659 13 | test_win_hotfix_reboot_identifier: Package_for_KB2913659~31bf3856ad364e35~amd64~~6.3.2.0 14 | -------------------------------------------------------------------------------- /tests/integration/targets/module_utils_SecurityIdentifier/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - block: 2 | - name: create test user 3 | win_user: 4 | name: test sid user 5 | password: ea4260e5-04b2-49a3-ac1b-a1c32c104ab2 6 | register: test_user 7 | 8 | - name: create test group 9 | win_group: 10 | name: test sid group 11 | state: present 12 | 13 | - name: get test group SID 14 | win_powershell: 15 | error_action: stop 16 | script: | 17 | $group = Get-LocalGroup -Name 'test sid group' 18 | $group.SID.Value 19 | register: test_group 20 | 21 | - name: test SecurityIdentifier 22 | security_identifier_test: 23 | user: test sid user 24 | user_sid: '{{ test_user.sid }}' 25 | group: test sid group 26 | group_sid: '{{ test_group.output[0] }}' 27 | 28 | always: 29 | - name: remove test user 30 | win_user: 31 | name: test sid user 32 | state: absent 33 | 34 | - name: remove test group 35 | win_group: 36 | name: test sid group 37 | state: absent 38 | -------------------------------------------------------------------------------- /tests/integration/targets/win_copy/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: create empty folder 3 | file: 4 | path: '{{role_path}}/files/subdir/empty' 5 | state: directory 6 | delegate_to: localhost 7 | 8 | # removes the cached zip module from the previous task so we can replicate 9 | # the below issue where win_copy would delete DEFAULT_LOCAL_TMP if it 10 | # had permission to 11 | # https://github.com/ansible/ansible/issues/35613 12 | - name: clear the local ansiballz cache 13 | file: 14 | path: "{{lookup('config', 'DEFAULT_LOCAL_TMP')}}/ansiballz_cache" 15 | state: absent 16 | delegate_to: localhost 17 | 18 | - name: create test folder 19 | win_file: 20 | path: '{{test_win_copy_path}}' 21 | state: directory 22 | 23 | - block: 24 | - name: run tests for local to remote 25 | include_tasks: tests.yml 26 | 27 | - name: run tests for remote to remote 28 | include_tasks: remote_tests.yml 29 | 30 | always: 31 | - name: remove test folder 32 | win_file: 33 | path: '{{test_win_copy_path}}' 34 | state: absent 35 | -------------------------------------------------------------------------------- /tests/integration/targets/win_audit_rule/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: create temporary directory to test with 2 | ansible.windows.win_file: 3 | path: "{{ test_audit_rule_directory }}" 4 | state: directory 5 | 6 | - name: create temporary file to test with 7 | ansible.windows.win_file: 8 | path: "{{ test_audit_rule_file }}" 9 | state: touch 10 | 11 | - name: create temporary registry key to test with 12 | ansible.windows.win_regedit: 13 | path: "{{ test_audit_rule_registry }}" 14 | 15 | - block: 16 | - include_tasks: add.yml 17 | - include_tasks: modify.yml 18 | - include_tasks: remove.yml 19 | always: 20 | - name: remove testing directory 21 | ansible.windows.win_file: 22 | path: "{{ test_audit_rule_directory }}" 23 | state: absent 24 | 25 | - name: remove testing file 26 | ansible.windows.win_file: 27 | path: "{{ test_audit_rule_file }}" 28 | state: absent 29 | 30 | - name: remove registry key 31 | ansible.windows.win_regedit: 32 | path: "{{ test_audit_rule_registry }}" 33 | state: absent 34 | -------------------------------------------------------------------------------- /.azure-pipelines/scripts/report-coverage.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Generate code coverage reports for uploading to Azure Pipelines and codecov.io. 3 | 4 | set -o pipefail -eu 5 | 6 | PATH="${PWD}/bin:${PATH}" 7 | 8 | if ! ansible-test --help >/dev/null 2>&1; then 9 | # Install the devel version of ansible-test for generating code coverage reports. 10 | # This is only used by Ansible Collections, which are typically tested against multiple Ansible versions (in separate jobs). 11 | # Since a version of ansible-test is required that can work the output from multiple older releases, the devel version is used. 12 | pip install https://github.com/ansible/ansible/archive/devel.tar.gz --disable-pip-version-check 13 | fi 14 | 15 | # Generate stubs using docker (if supported) otherwise fall back to using a virtual environment instead. 16 | # The use of docker is required when Powershell code is present, but Ansible 2.12 was the first version to support --docker with coverage. 17 | ansible-test coverage xml --group-by command --stub --docker --color -v || ansible-test coverage xml --group-by command --stub --venv --color -v -------------------------------------------------------------------------------- /tests/integration/targets/win_reg_stat/templates/test_reg.reg.j2: -------------------------------------------------------------------------------- 1 | Windows Registry Editor Version 5.00 2 | 3 | [HKEY_CURRENT_USER\{{ test_reg_path }}] 4 | 5 | [HKEY_CURRENT_USER\{{ test_reg_path }}\nested] 6 | "string"="test" 7 | "binary"=hex:01,16 8 | "dword"=dword:00000001 9 | "qword"=hex(b):01,00,00,00,00,00,00,00 10 | "large_dword"=dword:ffffffff 11 | "large_qword"=hex(b):ff,ff,ff,ff,ff,ff,ff,ff 12 | "multi"=hex(7):61,00,2c,00,20,00,62,00,00,00,63,00,00,00,00,00 13 | "expand"=hex(2):25,00,77,00,69,00,6e,00,64,00,69,00,72,00,25,00,5c,00,64,00,69,\ 14 | 00,72,00,00,00 15 | 16 | [HKEY_CURRENT_USER\{{ test_reg_path }}\nested\nest1] 17 | "dontcare"="" 18 | 19 | [HKEY_CURRENT_USER\{{ test_reg_path }}\nested\nest2] 20 | 21 | 22 | [HKEY_CURRENT_USER\{{ test_reg_path }}\single] 23 | "string1"="" 24 | "string2"="abc123" 25 | "none"=hex(0): 26 | "none1"=hex(0):00 27 | 28 | [HKEY_CURRENT_USER\{{ test_reg_path }}\Empty Default] 29 | 30 | 31 | [HKEY_CURRENT_USER\{{ test_reg_path }}\Blank Default] 32 | @="" 33 | "(Default)"="" 34 | 35 | [HKEY_CURRENT_USER\{{ test_reg_path }}\Duplicate Default] 36 | @="default" 37 | "(Default)"="custom" 38 | -------------------------------------------------------------------------------- /tests/integration/targets/win_route/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # test code for the win_psmodule module when using winrm connection 3 | # (c) 2017, Daniele Lazzari 4 | 5 | # This file is part of Ansible 6 | # 7 | # Ansible is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation, either version 3 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # Ansible is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with Ansible. If not, see . 19 | 20 | - block: 21 | - name: run all tasks 22 | include_tasks: tests.yml 23 | 24 | always: 25 | - name: remove test routes 26 | win_route: 27 | destination: "{{ destination_ip_address }}/32" 28 | state: absent 29 | register: route_removed 30 | -------------------------------------------------------------------------------- /tests/integration/targets/win_certificate_info/files/subj-cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIC0TCCAbkCCQC/MtOBa1UDpzANBgkqhkiG9w0BAQsFADAoMRkwFwYDVQQDDBBy 3 | b290LmFuc2libGUuY29tMQswCQYDVQQGEwJVUzAgFw0xNzEyMTUwODU2MzBaGA8y 4 | MDg2MDEwMjA4NTYzMFowKzEcMBoGA1UEAwwTc3ViamVjdC5hbnNpYmxlLmNvbTEL 5 | MAkGA1UEBhMCVVMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDszqdF 6 | So3GlVP1xUnN4bSPrFRFiOl/Mqup0Zn5UJJUR9wLnRD+OLcq7kKin6hYqozSu7cC 7 | +BnWQoq7vGSSNVqv7BqFMwzGJt9IBUQv0UqIQkA/duUdKdAiMn2PQRsNDnkWEbTj 8 | 4xsitItVNv84cDG0lkZBYyTgfyZlZLZWplkpUQkrZhoFCekZRJ+ODrqNW3W560rr 9 | OUIh+HiQeBqocat6OdxgICBqpUh8EVo1iha3DXjGN08q5utg6gmbIl2VBaVJjfyd 10 | wnUSqHylJwh6WCIEh+HXsn4ndfNWSN/fDqvi5I10V1j6Zos7yqQf8qAezUAm6eSq 11 | hLgZz0odq9DsO4HHAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAFK5mVIJ2D+kI0kk 12 | sxnW4ibWFjzlYFYPYrZg+2JFIVTbKBg1YzyhuIKm0uztqRxQq5iLn/C/uponHoqF 13 | 7KDQI37KAJIQdgSva+mEuO9bZAXg/eegail2hN6np7HjOKlPu23s40dAbFrbcOWP 14 | VbsBEPDP0HLv6OgbQWzNlE9HO1b7pX6ozk3q4ULO7IR85P6OHYsBBThL+qsOTzg/ 15 | gVknuB9+n9hgNqZcAcXBLDetOM9aEmYJCGk0enYP5UGLYpseE+rTXFbRuHTPr1o6 16 | e8BetiSWS/wcrV4ZF5qr9NiYt5eD6JzTB5Rn5awxxj0FwMtrBu003lLQUWxsuTzz 17 | 35/RLY4= 18 | -----END CERTIFICATE----- 19 | 20 | -------------------------------------------------------------------------------- /tests/integration/targets/win_certificate_store/files/subj-cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIC0TCCAbkCCQC/MtOBa1UDpzANBgkqhkiG9w0BAQsFADAoMRkwFwYDVQQDDBBy 3 | b290LmFuc2libGUuY29tMQswCQYDVQQGEwJVUzAgFw0xNzEyMTUwODU2MzBaGA8y 4 | MDg2MDEwMjA4NTYzMFowKzEcMBoGA1UEAwwTc3ViamVjdC5hbnNpYmxlLmNvbTEL 5 | MAkGA1UEBhMCVVMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDszqdF 6 | So3GlVP1xUnN4bSPrFRFiOl/Mqup0Zn5UJJUR9wLnRD+OLcq7kKin6hYqozSu7cC 7 | +BnWQoq7vGSSNVqv7BqFMwzGJt9IBUQv0UqIQkA/duUdKdAiMn2PQRsNDnkWEbTj 8 | 4xsitItVNv84cDG0lkZBYyTgfyZlZLZWplkpUQkrZhoFCekZRJ+ODrqNW3W560rr 9 | OUIh+HiQeBqocat6OdxgICBqpUh8EVo1iha3DXjGN08q5utg6gmbIl2VBaVJjfyd 10 | wnUSqHylJwh6WCIEh+HXsn4ndfNWSN/fDqvi5I10V1j6Zos7yqQf8qAezUAm6eSq 11 | hLgZz0odq9DsO4HHAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAFK5mVIJ2D+kI0kk 12 | sxnW4ibWFjzlYFYPYrZg+2JFIVTbKBg1YzyhuIKm0uztqRxQq5iLn/C/uponHoqF 13 | 7KDQI37KAJIQdgSva+mEuO9bZAXg/eegail2hN6np7HjOKlPu23s40dAbFrbcOWP 14 | VbsBEPDP0HLv6OgbQWzNlE9HO1b7pX6ozk3q4ULO7IR85P6OHYsBBThL+qsOTzg/ 15 | gVknuB9+n9hgNqZcAcXBLDetOM9aEmYJCGk0enYP5UGLYpseE+rTXFbRuHTPr1o6 16 | e8BetiSWS/wcrV4ZF5qr9NiYt5eD6JzTB5Rn5awxxj0FwMtrBu003lLQUWxsuTzz 17 | 35/RLY4= 18 | -----END CERTIFICATE----- 19 | 20 | -------------------------------------------------------------------------------- /.github/workflows/docs-push.yml: -------------------------------------------------------------------------------- 1 | name: Collection Docs 2 | concurrency: 3 | group: docs-push-${{ github.sha }} 4 | cancel-in-progress: true 5 | "on": 6 | push: 7 | branches: 8 | - main 9 | tags: 10 | - "*" 11 | schedule: 12 | - cron: "0 13 * * *" 13 | 14 | jobs: 15 | build-docs: 16 | permissions: 17 | contents: read 18 | name: Build Ansible Docs 19 | uses: ansible-community/github-docs-build/.github/workflows/_shared-docs-build-push.yml@main 20 | with: 21 | init-lenient: false 22 | init-fail-on-error: true 23 | 24 | publish-docs-gh-pages: 25 | # use to prevent running on forks 26 | if: github.repository == 'ansible-collections/ansible.windows' 27 | permissions: 28 | contents: write 29 | pages: write 30 | id-token: write 31 | needs: [build-docs] 32 | name: Publish Ansible Docs 33 | uses: ansible-community/github-docs-build/.github/workflows/_shared-docs-build-publish-gh-pages.yml@main 34 | with: 35 | artifact-name: ${{ needs.build-docs.outputs.artifact-name }} 36 | publish-gh-pages-branch: true 37 | secrets: 38 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 39 | -------------------------------------------------------------------------------- /tests/integration/targets/win_dsc/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Win_dsc test flow 3 | block: 4 | - name: Add remote temp dir to PSModulePath 5 | ansible.windows.win_path: 6 | name: PSModulePath 7 | state: present 8 | scope: machine 9 | elements: 10 | - '{{ remote_tmp_dir }}' 11 | 12 | # Needed so subsequent SSH session see the new PSModulePath env var 13 | - name: Restart sshd service 14 | ansible.windows.win_service: 15 | name: sshd 16 | state: restarted 17 | when: ansible_connection == 'ssh' 18 | 19 | - name: Reset connection meta 20 | ansible.builtin.meta: reset_connection 21 | 22 | - name: Copy custom DSC resources to remote temp dir 23 | ansible.windows.win_copy: 24 | src: files/ 25 | dest: '{{ remote_tmp_dir }}' 26 | 27 | - name: Run tests 28 | ansible.builtin.include_tasks: tests.yml 29 | 30 | always: 31 | - name: Remove remote tmp dir from PSModulePath 32 | ansible.windows.win_path: 33 | name: PSModulePath 34 | state: absent 35 | scope: machine 36 | elements: 37 | - '{{ remote_tmp_dir }}' 38 | -------------------------------------------------------------------------------- /tests/integration/targets/win_package/templates/registry_package.ps1.j2: -------------------------------------------------------------------------------- 1 | $ErrorActionPreference = 'Stop' 2 | 3 | $productId = '{{ registry_id }}' 4 | 5 | $regPath = switch ($args[0]) { 6 | HKLMx64 { 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall' } 7 | HKLMx86 { 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall' } 8 | HKCUx64 { 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall' } 9 | HKCUx86 { 'HKCU:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall' } 10 | default { throw "Invalid registry path specified $($args[0])" } 11 | } 12 | $regProperty = $args[1] 13 | $regUninstallString = $args[2] 14 | #$regUninstallString = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($args[2])) 15 | 16 | $null = New-Item -Path $regPath -Name $productId -Force 17 | 18 | $propParams = @{ 19 | Path = "$regPath\$productId" 20 | Force = $true 21 | PropertyType = 'String' 22 | } 23 | New-ItemProperty -Name $regProperty -Value $regUninstallString @propParams 24 | if ($regProperty -eq 'QuietUninstallString') { 25 | New-ItemProperty -Name 'UninstallString' -Value 'Fail if used' @propParams 26 | } 27 | -------------------------------------------------------------------------------- /plugins/modules/win_hostname.ps1: -------------------------------------------------------------------------------- 1 | #!powershell 2 | 3 | # Copyright: (c) 2018, Ripon Banik (@riponbanik) 4 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 5 | 6 | #AnsibleRequires -CSharpUtil Ansible.Basic 7 | 8 | $spec = @{ 9 | options = @{ 10 | name = @{ type = 'str'; required = $true } 11 | } 12 | supports_check_mode = $true 13 | } 14 | $module = [Ansible.Basic.AnsibleModule]::Create($args, $spec) 15 | 16 | $current_computer_name = (Get-CimInstance -Class Win32_ComputerSystem).DNSHostname 17 | 18 | $module.Result.old_name = $current_computer_name 19 | $module.Result.reboot_required = $false 20 | 21 | $module.Diff.before = $current_computer_name 22 | $module.Diff.after = $module.Params.name 23 | 24 | if ($module.Params.name -ne $current_computer_name) { 25 | Try { 26 | Rename-Computer -NewName $module.Params.name -Force -WhatIf:$module.CheckMode 27 | } 28 | Catch { 29 | $module.FailJson("Failed to rename computer to '$($module.Params.name)': $($_.Exception.Message)", $_) 30 | } 31 | $module.Result.changed = $true 32 | $module.Result.reboot_required = $true 33 | } 34 | 35 | $module.ExitJson() 36 | -------------------------------------------------------------------------------- /tests/integration/targets/win_hotfix/tasks/tests.yml: -------------------------------------------------------------------------------- 1 | # only basic tests, doesn't actually install/uninstall and hotfixes 2 | --- 3 | - name: fail when source isn't set 4 | win_hotfix: 5 | state: present 6 | register: fail_no_source 7 | failed_when: fail_no_source.msg != 'source must be set when state=present' 8 | 9 | - name: fail when identifier or kb isn't set on absent 10 | win_hotfix: 11 | state: absent 12 | register: fail_no_key 13 | failed_when: fail_no_key.msg != 'either hotfix_identifier or hotfix_kb needs to be set when state=absent' 14 | 15 | - name: remove an identifier that isn't installed 16 | win_hotfix: 17 | hotfix_identifier: fake~identifier 18 | state: absent 19 | register: remove_missing_hotfix_identifier 20 | 21 | - name: assert remove an identifier that isn't installed 22 | assert: 23 | that: 24 | - remove_missing_hotfix_identifier is not changed 25 | 26 | - name: remove a kb that isn't installed 27 | win_hotfix: 28 | hotfix_kb: KB123456 29 | state: absent 30 | register: remove_missing_hotfix_kb 31 | 32 | - name: assert remove a kb that isn't installed 33 | assert: 34 | that: 35 | - remove_missing_hotfix_kb is not changed 36 | -------------------------------------------------------------------------------- /tests/integration/targets/win_service/tasks/driver.yml: -------------------------------------------------------------------------------- 1 | # https://github.com/ansible-collections/ansible.windows/issues/115 2 | # In lieu of having our own driver which we control, we just test with a inconsequential driver in CI. 3 | - name: get existing display name for driver 4 | win_service_info: 5 | name: cdrom 6 | register: driver_info 7 | 8 | - block: 9 | - name: open driver service and set display name 10 | win_service: 11 | name: cdrom 12 | display_name: Ansible Display Name 13 | register: driver_change_display 14 | 15 | - name: get result of open driver service and set display name 16 | win_service_info: 17 | name: cdrom 18 | register: driver_change_display_actual 19 | 20 | - name: assert open driver service and set display name 21 | assert: 22 | that: 23 | - driver_change_display is changed 24 | - driver_change_display.display_name == 'Ansible Display Name' 25 | - driver_change_display_actual.services[0].display_name == 'Ansible Display Name' 26 | 27 | always: 28 | - name: reset display name back to default 29 | win_service: 30 | name: cdrom 31 | display_name: '{{ driver_info.services[0].display_name }}' 32 | -------------------------------------------------------------------------------- /tests/integration/targets/app_control/handlers/main.yml: -------------------------------------------------------------------------------- 1 | - name: remove local tmp 2 | file: 3 | path: '{{ local_tmp.path }}' 4 | state: absent 5 | delegate_to: localhost 6 | 7 | - name: remove OpenAuthenticode module 8 | shell: Uninstall-PSResource -Name OpenAuthenticode -Version 0.6.1 9 | args: 10 | executable: pwsh 11 | delegate_to: localhost 12 | 13 | - name: remove WDAC certificates 14 | win_powershell: 15 | parameters: 16 | CAThumbprint: '{{ cert_info.output[0].ca_thumbprint }}' 17 | CertThumbprint: '{{ cert_info.output[0].thumbprint }}' 18 | script: | 19 | [CmdletBinding()] 20 | param ( 21 | [Parameter(Mandatory)] 22 | [string] 23 | $CAThumbprint, 24 | 25 | [Parameter(Mandatory)] 26 | [string] 27 | $CertThumbprint 28 | ) 29 | 30 | $ErrorActionPreference = 'Stop' 31 | 32 | Remove-Item -LiteralPath "Cert:\LocalMachine\Root\$CAThumbprint" -Force 33 | Remove-Item -LiteralPath "Cert:\LocalMachine\TrustedPublisher\$CertThumbprint" -Force 34 | 35 | - name: remove signed content 36 | file: 37 | path: '{{ item }}' 38 | state: absent 39 | delegate_to: localhost 40 | loop: '{{ sign_result.stdout_lines }}' 41 | -------------------------------------------------------------------------------- /tests/integration/targets/win_user_profile/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: set custom user facts 3 | set_fact: 4 | test_username: ansible_test 5 | test_password: '{{ "password123!" + lookup("password", "/dev/null chars=ascii_letters,digits length=9") }}' 6 | 7 | - name: create test account 8 | ansible.windows.win_user: 9 | name: '{{ test_username }}' 10 | password: '{{ test_password }}' 11 | state: present 12 | register: test_username_info 13 | 14 | - block: 15 | - name: check if profile exists 16 | ansible.windows.win_stat: 17 | path: C:\temp\{{ test_username }} 18 | register: profile_path 19 | 20 | - name: assert that profile doesn't exist before the test 21 | assert: 22 | that: 23 | - not profile_path.stat.exists 24 | 25 | - name: run tests 26 | include_tasks: tests.yml 27 | 28 | always: 29 | - name: remove test account 30 | ansible.windows.win_user: 31 | name: '{{ test_username }}' 32 | state: absent 33 | 34 | - name: remove test account profile 35 | win_user_profile: 36 | name: '{{ item }}' 37 | state: absent 38 | remove_multiple: True 39 | with_items: 40 | - '{{ test_username }}' 41 | - '{{ test_username }}.000' 42 | - test_username_profile 43 | -------------------------------------------------------------------------------- /tests/integration/targets/win_dns_record/tasks/tests.yml: -------------------------------------------------------------------------------- 1 | - name: ensure DNS services are installed 2 | ansible.windows.win_feature: 3 | name: DNS 4 | state: present 5 | register: dns_install 6 | 7 | - name: reboot server if needed 8 | ansible.windows.win_reboot: 9 | when: dns_install.reboot_required 10 | 11 | - name: Clean slate 12 | import_tasks: clean.yml 13 | vars: 14 | fail_on_missing: false 15 | 16 | - block: 17 | - name: Create the forward zone 18 | ansible.windows.win_shell: Add-DnsServerPrimaryZone -Name '{{ win_dns_record_zone }}' -ZoneFile '{{ win_dns_record_zone}}.dns' 19 | - name: Create the reverse zone 20 | ansible.windows.win_shell: Add-DnsServerPrimaryZone -NetworkID '{{ win_dns_record_revzone_network }}' -ZoneFile '{{ win_dns_record_revzone}}.dns' 21 | 22 | - import_tasks: tests-A.yml 23 | - import_tasks: tests-AAAA.yml 24 | - import_tasks: tests-NS.yml 25 | - import_tasks: tests-SRV.yml 26 | - import_tasks: tests-CNAME.yml 27 | - import_tasks: tests-DHCID.yml 28 | - import_tasks: tests-PTR.yml 29 | - import_tasks: tests-TXT.yml 30 | - import_tasks: tests-diff.yml 31 | 32 | always: 33 | - name: Clean slate 34 | import_tasks: clean.yml 35 | vars: 36 | fail_on_missing: true 37 | -------------------------------------------------------------------------------- /tests/integration/targets/win_certificate_info/files/root-cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDKDCCAhCgAwIBAgIJAP1vIdGgMJv/MA0GCSqGSIb3DQEBCwUAMCgxGTAXBgNV 3 | BAMMEHJvb3QuYW5zaWJsZS5jb20xCzAJBgNVBAYTAlVTMCAXDTE3MTIxNTA4Mzkz 4 | MloYDzIwODYwMTAyMDgzOTMyWjAoMRkwFwYDVQQDDBByb290LmFuc2libGUuY29t 5 | MQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMmq 6 | YT8eZY6rFQKnmScUGnnUH1tLQ+3WQpfKiWygCUSb1CNqO3J1u3pGMEqYM58LK4Kr 7 | Mpskv7K1tCV/EMZqGTqXAIfSLy9umlb/9C3AhL9thBPn5I9dam/EmrIZktI9/w5Y 8 | wBXn4toe+OopA3QkMQh9BUjUCPb9fdOI+ir7OGFZMmxXmiM64+BEeywM2oSGsdZ9 9 | 5hU378UBu2IX4+OAV8Fbr2l6VW+Fxg/tKIOo6Bs46Pa4EZgtemOqs3kxYBOltBTb 10 | vFcLsLa4KYVu5Ge5YfB0Axfaem7PoP8IlMs8gxyojZ/r0o5hzxUcYlL/h8GeeoLW 11 | PFFdiAS+UgxWINOqNXMCAwEAAaNTMFEwHQYDVR0OBBYEFLp9k4LmOnAR4ROrqhb+ 12 | CFdbk2+oMB8GA1UdIwQYMBaAFLp9k4LmOnAR4ROrqhb+CFdbk2+oMA8GA1UdEwEB 13 | /wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAGksycHsjGbXfWfuhQh+CvXk/A2v 14 | MoNgiHtNMTGliVNgoVp1B1rj4x9xyZ8YrO8GAmv8jaCwCShd0B5Ul4aZVk1wglVv 15 | lFAwb4IAZN9jv9+fw5BRzQ2tLhkVWIEwx6pZkhGhhjBvMaplLN5JwBtsdZorFbm7 16 | wuKiUKcFAM28acoOhCmOhgyNNBZpZn5wXaQDY43AthJOhitAV7vph4MPUkwIJnOh 17 | MA5GJXEqS58TE9z9pkhQnn9598G8tmOXyA2erAoM9JAXM3EYHxVpoHBb9QRj6WAw 18 | XVBo6qRXkwjNEM5CbnD4hVIBsdkOGsDrgd4Q5izQZ3x+jFNkdL/zPsXjJFw= 19 | -----END CERTIFICATE----- 20 | 21 | -------------------------------------------------------------------------------- /tests/integration/targets/win_certificate_store/files/root-cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDKDCCAhCgAwIBAgIJAP1vIdGgMJv/MA0GCSqGSIb3DQEBCwUAMCgxGTAXBgNV 3 | BAMMEHJvb3QuYW5zaWJsZS5jb20xCzAJBgNVBAYTAlVTMCAXDTE3MTIxNTA4Mzkz 4 | MloYDzIwODYwMTAyMDgzOTMyWjAoMRkwFwYDVQQDDBByb290LmFuc2libGUuY29t 5 | MQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMmq 6 | YT8eZY6rFQKnmScUGnnUH1tLQ+3WQpfKiWygCUSb1CNqO3J1u3pGMEqYM58LK4Kr 7 | Mpskv7K1tCV/EMZqGTqXAIfSLy9umlb/9C3AhL9thBPn5I9dam/EmrIZktI9/w5Y 8 | wBXn4toe+OopA3QkMQh9BUjUCPb9fdOI+ir7OGFZMmxXmiM64+BEeywM2oSGsdZ9 9 | 5hU378UBu2IX4+OAV8Fbr2l6VW+Fxg/tKIOo6Bs46Pa4EZgtemOqs3kxYBOltBTb 10 | vFcLsLa4KYVu5Ge5YfB0Axfaem7PoP8IlMs8gxyojZ/r0o5hzxUcYlL/h8GeeoLW 11 | PFFdiAS+UgxWINOqNXMCAwEAAaNTMFEwHQYDVR0OBBYEFLp9k4LmOnAR4ROrqhb+ 12 | CFdbk2+oMB8GA1UdIwQYMBaAFLp9k4LmOnAR4ROrqhb+CFdbk2+oMA8GA1UdEwEB 13 | /wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAGksycHsjGbXfWfuhQh+CvXk/A2v 14 | MoNgiHtNMTGliVNgoVp1B1rj4x9xyZ8YrO8GAmv8jaCwCShd0B5Ul4aZVk1wglVv 15 | lFAwb4IAZN9jv9+fw5BRzQ2tLhkVWIEwx6pZkhGhhjBvMaplLN5JwBtsdZorFbm7 16 | wuKiUKcFAM28acoOhCmOhgyNNBZpZn5wXaQDY43AthJOhitAV7vph4MPUkwIJnOh 17 | MA5GJXEqS58TE9z9pkhQnn9598G8tmOXyA2erAoM9JAXM3EYHxVpoHBb9QRj6WAw 18 | XVBo6qRXkwjNEM5CbnD4hVIBsdkOGsDrgd4Q5izQZ3x+jFNkdL/zPsXjJFw= 19 | -----END CERTIFICATE----- 20 | 21 | -------------------------------------------------------------------------------- /tests/unit/test_data/win_updates/install_reboot_two_failures.txt: -------------------------------------------------------------------------------- 1 | {"task":"exit","result":{"exception":{"exception":"Exception from HRESULT: 0x80240032\r\nAt line:496 char:21\r\n+ throw $exp\r\n+ ~~~~~~~~~~\r\n + CategoryInfo : OperationStopped: (:) [], COMException\r\n + FullyQualifiedErrorId : Exception from HRESULT: 0x80240032\r\n \r\n\r\n\r\nat Invoke-AsyncMethod, \u003cNo file\u003e: line 496\r\nat \u003cScriptBlock\u003e, \u003cNo file\u003e: line 728","message":"Searching for updates: Exception from HRESULT: 0x80240032","hresult":-2145124302},"reboot_required":true,"failed":true,"changed":false}} 2 | 3 | {"changed": false} 4 | 5 | {"task":"exit","result":{"exception":{"exception":"Exception from HRESULT: 0x80240032\r\nAt line:496 char:21\r\n+ throw $exp\r\n+ ~~~~~~~~~~\r\n + CategoryInfo : OperationStopped: (:) [], COMException\r\n + FullyQualifiedErrorId : Exception from HRESULT: 0x80240032\r\n \r\n\r\n\r\nat Invoke-AsyncMethod, \u003cNo file\u003e: line 496\r\nat \u003cScriptBlock\u003e, \u003cNo file\u003e: line 728","message":"Searching for updates: Exception from HRESULT: 0x80240032","hresult":-2145124302},"reboot_required":false,"failed":true,"changed":false}} 6 | 7 | {"changed": false} 8 | -------------------------------------------------------------------------------- /plugins/modules/win_hostname.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright: (c) 2018, Ripon Banik (@riponbanik) 5 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 6 | 7 | DOCUMENTATION = r''' 8 | module: win_hostname 9 | short_description: Manages local Windows computer name 10 | description: 11 | - Manages local Windows computer name. 12 | - A reboot is required for the computer name to take effect. 13 | options: 14 | name: 15 | description: 16 | - The hostname to set for the computer. 17 | type: str 18 | required: true 19 | seealso: 20 | - module: ansible.windows.win_dns_client 21 | author: 22 | - Ripon Banik (@riponbanik) 23 | ''' 24 | 25 | EXAMPLES = r''' 26 | - name: Change the hostname to sample-hostname 27 | ansible.windows.win_hostname: 28 | name: sample-hostname 29 | register: res 30 | 31 | - name: Reboot 32 | ansible.windows.win_reboot: 33 | when: res.reboot_required 34 | ''' 35 | 36 | RETURN = r''' 37 | old_name: 38 | description: The original hostname that was set before it was changed. 39 | returned: always 40 | type: str 41 | sample: old_hostname 42 | reboot_required: 43 | description: Whether a reboot is required to complete the hostname change. 44 | returned: always 45 | type: bool 46 | sample: true 47 | ''' 48 | -------------------------------------------------------------------------------- /tests/integration/targets/win_service/tasks/sid_info.yml: -------------------------------------------------------------------------------- 1 | - name: set sid info (check) 2 | win_service: 3 | name: '{{ test_win_service_name }}' 4 | sid_info: restricted 5 | register: set_sid_info_check 6 | check_mode: yes 7 | 8 | - name: get result of set sid info (check) 9 | win_service_info: 10 | name: '{{ test_win_service_name }}' 11 | register: set_sid_info_actual_check 12 | 13 | - name: assert set sid info (check) 14 | assert: 15 | that: 16 | - set_sid_info_check is changed 17 | - set_sid_info_actual_check.services[0].sid_info == 'none' 18 | 19 | - name: set sid info 20 | win_service: 21 | name: '{{ test_win_service_name }}' 22 | sid_info: restricted 23 | register: set_type 24 | 25 | - name: get result of set sid info 26 | win_service_info: 27 | name: '{{ test_win_service_name }}' 28 | register: set_sid_info_actual 29 | 30 | - name: assert set sid info 31 | assert: 32 | that: 33 | - set_type is changed 34 | - set_sid_info_actual.services[0].sid_info == 'restricted' 35 | 36 | - name: set sid info (idempotent) 37 | win_service: 38 | name: '{{ test_win_service_name }}' 39 | sid_info: restricted 40 | register: set_sid_info_again 41 | 42 | - name: assert set sid info (idempotent) 43 | assert: 44 | that: 45 | - not set_sid_info_again is changed 46 | -------------------------------------------------------------------------------- /.azure-pipelines/templates/coverage.yml: -------------------------------------------------------------------------------- 1 | # This template adds a job for processing code coverage data. 2 | # It will upload results to Azure Pipelines and codecov.io. 3 | # Use it from a job stage that completes after all other jobs have completed. 4 | # This can be done by placing it in a separate summary stage that runs after the test stage(s) have completed. 5 | 6 | jobs: 7 | - job: Coverage 8 | displayName: Code Coverage 9 | container: $[ variables.defaultContainer ] 10 | workspace: 11 | clean: all 12 | steps: 13 | - checkout: self 14 | fetchDepth: $(fetchDepth) 15 | path: $(checkoutPath) 16 | - task: DownloadPipelineArtifact@2 17 | displayName: Download Coverage Data 18 | inputs: 19 | path: coverage/ 20 | patterns: "Coverage */*=coverage.combined" 21 | - bash: .azure-pipelines/scripts/combine-coverage.py coverage/ 22 | displayName: Combine Coverage Data 23 | - bash: .azure-pipelines/scripts/report-coverage.sh 24 | displayName: Generate Coverage Report 25 | condition: gt(variables.coverageFileCount, 0) 26 | - bash: .azure-pipelines/scripts/publish-codecov.py "$(outputPath)" 27 | displayName: Publish to codecov.io 28 | condition: gt(variables.coverageFileCount, 0) 29 | continueOnError: true 30 | -------------------------------------------------------------------------------- /tests/integration/targets/win_get_url/library/win_defender_exclusion.ps1: -------------------------------------------------------------------------------- 1 | #!powershell 2 | 3 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | 5 | #Requires -Module Ansible.ModuleUtils.Legacy 6 | 7 | $params = Parse-Args $args -supports_check_mode $true 8 | 9 | $path = Get-AnsibleParam -obj $params -name "path" -type "path" -failifempty $true 10 | $state = Get-AnsibleParam -obj $params -name "state" -type "str" -default "present" -validateset "absent", "present" 11 | 12 | $result = @{ 13 | changed = $false 14 | } 15 | 16 | # This is a test module, just skip instead of erroring out if we cannot set the rule 17 | if ($null -eq (Get-Command -Name Get-MpPreference -ErrorAction SilentlyContinue)) { 18 | $result.skipped = $true 19 | $result.msg = "Skip as cannot set exclusion rule" 20 | Exit-Json -obj $result 21 | } 22 | 23 | $exclusions = (Get-MpPreference).ExclusionPath 24 | if ($null -eq $exclusions) { 25 | $exclusions = @() 26 | } 27 | 28 | if ($state -eq "absent") { 29 | if ($path -in $exclusions) { 30 | Remove-MpPreference -ExclusionPath $path 31 | $result.changed = $true 32 | } 33 | } 34 | else { 35 | if ($path -notin $exclusions) { 36 | Add-MpPreference -ExclusionPath $path 37 | $result.changed = $true 38 | } 39 | } 40 | 41 | Exit-Json -obj $result 42 | -------------------------------------------------------------------------------- /tests/integration/targets/app_control/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: get OS version 2 | win_powershell: 3 | script: (Get-Item -LiteralPath $env:SystemRoot\System32\kernel32.dll).VersionInfo.ProductVersion.ToString() 4 | changed_when: False 5 | register: os_version 6 | 7 | - name: check if pwsh is installed locally 8 | shell: command -V pwsh 9 | delegate_to: localhost 10 | failed_when: False 11 | changed_when: False 12 | register: pwsh_stat 13 | 14 | - name: run tests if pwsh is present and running on Server 2019 or later 15 | when: 16 | - pwsh_stat.rc == 0 17 | - os_version.output[0] is version('10.0.17763', '>=') 18 | block: 19 | - name: setup App Control 20 | import_tasks: setup.yml 21 | 22 | - name: run App Control tests 23 | import_tasks: test.yml 24 | 25 | always: 26 | - name: disable policy through CiTool if present 27 | win_command: CiTool.exe --remove-policy {{ policy_info.output[0].policy_id }} 28 | when: 29 | - policy_info is defined 30 | - policy_info.output[0].policy_id is truthy 31 | 32 | - name: remove App Control policy 33 | win_file: 34 | path: '{{ policy_info.output[0].path }}' 35 | state: absent 36 | register: policy_removal 37 | when: 38 | - policy_info is defined 39 | 40 | - name: reboot after removing policy file 41 | win_reboot: 42 | when: policy_removal is changed 43 | -------------------------------------------------------------------------------- /tests/integration/targets/win_service/tasks/service_type.yml: -------------------------------------------------------------------------------- 1 | - name: set service type (check) 2 | win_service: 3 | name: '{{ test_win_service_name }}' 4 | service_type: win32_share_process 5 | register: set_type_check 6 | check_mode: yes 7 | 8 | - name: get result of set service type (check) 9 | win_service_info: 10 | name: '{{ test_win_service_name }}' 11 | register: set_type_actual_check 12 | 13 | - name: assert set service type (check) 14 | assert: 15 | that: 16 | - set_type_check is changed 17 | - set_type_actual_check.services[0].service_type == 'win32_own_process' 18 | 19 | - name: set service type 20 | win_service: 21 | name: '{{ test_win_service_name }}' 22 | service_type: win32_share_process 23 | register: set_type 24 | 25 | - name: get result of set service type 26 | win_service_info: 27 | name: '{{ test_win_service_name }}' 28 | register: set_type_actual 29 | 30 | - name: assert set service type 31 | assert: 32 | that: 33 | - set_type is changed 34 | - set_type_actual.services[0].service_type == 'win32_share_process' 35 | 36 | - name: set service type (idempotent) 37 | win_service: 38 | name: '{{ test_win_service_name }}' 39 | service_type: win32_share_process 40 | register: set_type_again 41 | 42 | - name: assert set service type (idempotent) 43 | assert: 44 | that: 45 | - not set_type_again is changed 46 | -------------------------------------------------------------------------------- /plugins/modules/win_ping.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright: (c) 2012, Michael DeHaan , and others 5 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 6 | 7 | DOCUMENTATION = r''' 8 | --- 9 | module: win_ping 10 | short_description: A windows version of the classic ping module 11 | description: 12 | - Checks management connectivity of a windows host. 13 | - This is NOT ICMP ping, this is just a trivial test module. 14 | - For non-Windows targets, use the M(ansible.builtin.ping) module instead. 15 | options: 16 | data: 17 | description: 18 | - Alternate data to return instead of 'pong'. 19 | - If this parameter is set to C(crash), the module will cause an exception. 20 | type: str 21 | default: pong 22 | seealso: 23 | - module: ansible.builtin.ping 24 | author: 25 | - Chris Church (@cchurch) 26 | ''' 27 | 28 | EXAMPLES = r''' 29 | # Test connectivity to a windows host 30 | # ansible winserver -m ansible.windows.win_ping 31 | 32 | - name: Example from an Ansible Playbook 33 | ansible.windows.win_ping: 34 | 35 | - name: Induce an exception to see what happens 36 | ansible.windows.win_ping: 37 | data: crash 38 | ''' 39 | 40 | RETURN = r''' 41 | ping: 42 | description: Value provided with the data parameter. 43 | returned: success 44 | type: str 45 | sample: pong 46 | ''' 47 | -------------------------------------------------------------------------------- /tests/integration/targets/win_group_membership/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Gather facts 2 | ansible.builtin.setup: 3 | 4 | - name: Remove potentially leftover test group 5 | ansible.windows.win_group: &wg_absent 6 | name: WinGroupMembershipTest 7 | state: absent 8 | 9 | - name: Remove potentially leftover test user 10 | ansible.windows.win_user: &wu_absent 11 | name: WinTestUser 12 | state: absent 13 | 14 | - name: Add new test group 15 | ansible.windows.win_group: 16 | name: WinGroupMembershipTest 17 | state: present 18 | 19 | - name: Add new test user 20 | ansible.windows.win_user: 21 | name: WinTestUser 22 | password: "W1nGr0upM3mb3rsh1pT3$tP@$$w0rd" 23 | state: present 24 | 25 | - name: Run tests for win_group_membership 26 | block: 27 | - name: Test in normal mode 28 | ansible.builtin.import_tasks: tests.yml 29 | vars: 30 | win_local_group: WinGroupMembershipTest 31 | win_local_user: WinTestUser 32 | in_check_mode: false 33 | 34 | - name: Test in check-mode 35 | ansible.builtin.import_tasks: tests.yml 36 | vars: 37 | win_local_group: WinGroupMembershipTest 38 | win_local_user: WinTestUser 39 | in_check_mode: true 40 | check_mode: true 41 | 42 | - name: Remove test group 43 | ansible.windows.win_group: *wg_absent 44 | 45 | - name: Remove test user 46 | ansible.windows.win_group: *wu_absent 47 | -------------------------------------------------------------------------------- /tests/integration/targets/win_service/tasks/error_control.yml: -------------------------------------------------------------------------------- 1 | - name: set error control (check) 2 | win_service: 3 | name: '{{ test_win_service_name }}' 4 | error_control: ignore 5 | register: set_error_control_check 6 | check_mode: yes 7 | 8 | - name: get result of set error control (check) 9 | win_service_info: 10 | name: '{{ test_win_service_name }}' 11 | register: set_error_control_actual_check 12 | 13 | - name: assert set error control (check) 14 | assert: 15 | that: 16 | - set_error_control_check is changed 17 | - set_error_control_actual_check.services[0].error_control == 'normal' 18 | 19 | - name: set error control 20 | win_service: 21 | name: '{{ test_win_service_name }}' 22 | error_control: ignore 23 | register: set_type 24 | 25 | - name: get result of set error control 26 | win_service_info: 27 | name: '{{ test_win_service_name }}' 28 | register: set_error_control_actual 29 | 30 | - name: assert set error control 31 | assert: 32 | that: 33 | - set_type is changed 34 | - set_error_control_actual.services[0].error_control == 'ignore' 35 | 36 | - name: set error control (idempotent) 37 | win_service: 38 | name: '{{ test_win_service_name }}' 39 | error_control: ignore 40 | register: set_error_control_again 41 | 42 | - name: assert set error control (idempotent) 43 | assert: 44 | that: 45 | - not set_error_control_again is changed 46 | -------------------------------------------------------------------------------- /tests/integration/targets/win_package/library/prereq_setup.ps1: -------------------------------------------------------------------------------- 1 | #!powershell 2 | 3 | # Copyright: (c) 2024, Ansible Project 4 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 5 | 6 | #AnsibleRequires -CSharpUtil Ansible.Basic 7 | 8 | 9 | $module = [Ansible.Basic.AnsibleModule]::Create($args, @{}) 10 | 11 | # Server 2025 fails to run Get-AppxPackage and other DISM module commands in 12 | # a PSRemoting (psrp) session as it has a dependency on some dll's not present 13 | # in the GAC and only in the powershell.exe directory. As PSRP runs through 14 | # wsmprovhost.exe, it fails to find those dlls. This hack will manually load 15 | # the 4 requires dlls into the GAC so our tests can work. This is a hack and 16 | # should be removed in the future if MS fix their bug on 2025. 17 | try { 18 | $null = Get-AppxPackage 19 | } 20 | catch { 21 | Add-Type -AssemblyName "System.EnterpriseServices" 22 | $publish = [System.EnterpriseServices.Internal.Publish]::new() 23 | 24 | @( 25 | 'System.Numerics.Vectors.dll', 26 | 'System.Runtime.CompilerServices.Unsafe.dll', 27 | 'System.Security.Principal.Windows.dll', 28 | 'System.Memory.dll' 29 | ) | ForEach-Object { 30 | $dllPath = "$env:SystemRoot\System32\WindowsPowerShell\v1.0\$_" 31 | $publish.GacInstall($dllPath) 32 | } 33 | 34 | $module.Result.changed = $true 35 | } 36 | 37 | $module.ExitJson() 38 | -------------------------------------------------------------------------------- /tests/integration/targets/win_package/files/good.wsx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "python.testing.pytestArgs": [ 3 | "tests/unit", 4 | "-vv" 5 | ], 6 | "python.testing.unittestEnabled": false, 7 | "python.testing.pytestEnabled": true, 8 | "python.analysis.extraPaths": [ 9 | "${workspaceFolder}/../../../", 10 | ], 11 | "powershell.codeFormatting.addWhitespaceAroundPipe": true, 12 | "powershell.codeFormatting.alignPropertyValuePairs": false, 13 | "powershell.codeFormatting.autoCorrectAliases": true, 14 | "powershell.codeFormatting.ignoreOneLineBlock": true, 15 | "powershell.codeFormatting.newLineAfterCloseBrace": true, 16 | "powershell.codeFormatting.newLineAfterOpenBrace": true, 17 | "powershell.codeFormatting.openBraceOnSameLine": true, 18 | "powershell.codeFormatting.pipelineIndentationStyle": "IncreaseIndentationForFirstPipeline", 19 | "powershell.codeFormatting.whitespaceAfterSeparator": true, 20 | "powershell.codeFormatting.whitespaceAroundOperator": true, 21 | "powershell.codeFormatting.whitespaceBeforeOpenBrace": true, 22 | "powershell.codeFormatting.whitespaceBeforeOpenParen": true, 23 | "powershell.codeFormatting.whitespaceBetweenParameters": true, 24 | "powershell.codeFormatting.whitespaceInsideBrace": true, 25 | "powershell.codeFormatting.avoidSemicolonsAsLineTerminators": true, 26 | "powershell.scriptAnalysis.enable": true, 27 | "[powershell]": { 28 | "editor.formatOnSave": true, 29 | }, 30 | } 31 | -------------------------------------------------------------------------------- /tests/integration/targets/win_auto_logon/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: get user domain split for ansible_user 3 | ansible.windows.win_shell: | 4 | $account = New-Object -TypeName System.Security.Principal.NTAccount -ArgumentList '{{ ansible_user }}' 5 | $sid = $account.Translate([System.Security.Principal.SecurityIdentifier]) 6 | $sid.Translate([System.Security.Principal.NTAccount]).Value -split '{{ "\\" }}' 7 | changed_when: False 8 | register: test_user_split 9 | 10 | - set_fact: 11 | test_domain: '{{ test_user_split.stdout_lines[0] }}' 12 | test_user: '{{ test_user_split.stdout_lines[1] }}' 13 | 14 | - name: ensure auto logon is cleared before test 15 | win_auto_logon: 16 | state: absent 17 | 18 | - name: ensure defaults are set 19 | ansible.windows.win_regedit: 20 | path: HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon 21 | name: '{{ item.name }}' 22 | data: '{{ item.value }}' 23 | type: '{{ item.type }}' 24 | state: present 25 | loop: 26 | # We set the DefaultPassword to ensure win_auto_logon clears this out 27 | - name: DefaultPassword 28 | value: abc 29 | type: string 30 | # Ensures the host we test on has a baseline key to check against 31 | - name: AutoAdminLogon 32 | value: 0 33 | type: dword 34 | 35 | - block: 36 | - name: run tests 37 | include_tasks: tests.yml 38 | 39 | always: 40 | - name: make sure the auto logon is cleared 41 | win_auto_logon: 42 | state: absent 43 | -------------------------------------------------------------------------------- /plugins/modules/win_owner.yml: -------------------------------------------------------------------------------- 1 | # Copyright: (c) 2015, Hans-Joachim Kliemeck 2 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 3 | 4 | DOCUMENTATION: 5 | module: win_owner 6 | short_description: Set owner 7 | description: 8 | - Set owner of files or directories. 9 | options: 10 | path: 11 | description: 12 | - Path to be used for changing owner. 13 | type: path 14 | required: true 15 | user: 16 | description: 17 | - Name to be used for changing owner. 18 | - This value can be in the form of a SecurityIdentifier string, a user 19 | or group in the Netlogon C(DOMAIN\User) or UPN format 20 | (user@DOMAIN.COM). 21 | type: str 22 | required: true 23 | recurse: 24 | description: 25 | - Indicates if the owner should be changed recursively. 26 | type: bool 27 | default: false 28 | seealso: 29 | - module: ansible.windows.win_acl 30 | - module: ansible.windows.win_file 31 | - module: ansible.windows.win_stat 32 | author: 33 | - Hans-Joachim Kliemeck (@h0nIg) 34 | 35 | EXAMPLES: | 36 | - name: Change owner of path 37 | ansible.windows.win_owner: 38 | path: C:\apache 39 | user: apache 40 | recurse: true 41 | 42 | - name: Set the owner of root directory 43 | ansible.windows.win_owner: 44 | path: C:\apache 45 | user: SYSTEM 46 | recurse: false 47 | 48 | RETURN: {} 49 | -------------------------------------------------------------------------------- /tests/integration/targets/win_dhcp_lease/tasks/tests_checkmode.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Check DHCP Service/Role Install State 3 | ansible.windows.win_feature: 4 | name: DHCP 5 | state: present 6 | include_management_tools: yes 7 | register: dhcp_role 8 | check_mode: true 9 | 10 | - name: Reboot if Necessary 11 | ansible.windows.win_reboot: 12 | when: dhcp_role.reboot_required 13 | check_mode: true 14 | 15 | - name: Remove DHCP Address by IP 16 | win_dhcp_lease: 17 | state: absent 18 | ip: "{{ dhcp_lease_ip }}" 19 | check_mode: true 20 | 21 | - name: Create Lease 22 | win_dhcp_lease: 23 | type: lease 24 | ip: "{{ dhcp_lease_ip }}" 25 | scope_id: "{{ dhcp_scope_id }}" 26 | mac: "{{ dhcp_lease_mac }}" 27 | dns_hostname: "{{ dhcp_lease_hostname }}" 28 | dns_regtype: noreg 29 | description: This is a description! 30 | check_mode: true 31 | 32 | - name: Create Reservation 33 | win_dhcp_lease: 34 | type: reservation 35 | ip: "{{ dhcp_lease_ip }}" 36 | mac: "{{ dhcp_lease_mac }}" 37 | scope_id: "{{ dhcp_scope_id }}" 38 | check_mode: true 39 | 40 | - name: Create Reservation w/Description 41 | win_dhcp_lease: 42 | type: reservation 43 | ip: "{{ dhcp_lease_ip }}" 44 | mac: "{{ dhcp_lease_mac }}" 45 | scope_id: "{{ dhcp_scope_id }}" 46 | description: This is a Description! 47 | check_mode: true 48 | 49 | - name: Remove DHCP Reservation by MAC 50 | win_dhcp_lease: 51 | state: absent 52 | mac: "{{ dhcp_lease_mac }}" 53 | -------------------------------------------------------------------------------- /tests/integration/targets/win_dsc/files/xTestDsc/1.0.0/DSCResources/ANSIBLE_xSetReboot/ANSIBLE_xSetReboot.psm1: -------------------------------------------------------------------------------- 1 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSDSCDscExamplesPresent", "")] 2 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSDSCDscTestsPresent", "")] 3 | param() 4 | 5 | #Requires -Version 5.0 -Modules CimCmdlets 6 | 7 | Function Get-TargetResource { 8 | [CmdletBinding()] 9 | [OutputType([Hashtable])] 10 | param( 11 | [Parameter(Mandatory = $true)] 12 | [ValidateNotNullOrEmpty()] 13 | [String]$KeyParam 14 | ) 15 | Write-Verbose -Message "In Get-TargetResource" 16 | @{ Value = [bool](Get-Variable -Name DSCMachineStatus -Scope Global -ValueOnly) } 17 | } 18 | 19 | Function Set-TargetResource { 20 | [CmdletBinding()] 21 | param ( 22 | [Parameter(Mandatory = $true)] 23 | [ValidateNotNullOrEmpty()] 24 | [String]$KeyParam, 25 | [Bool]$Value = $true 26 | ) 27 | Write-Verbose -Message "In Set-TargetResource" 28 | Set-Variable -Name DSCMachineStatus -Scope Global -Value ([int]$Value) 29 | } 30 | 31 | Function Test-TargetResource { 32 | [CmdletBinding()] 33 | [OutputType([Boolean])] 34 | param ( 35 | [Parameter(Mandatory = $true)] 36 | [ValidateNotNullOrEmpty()] 37 | [String]$KeyParam, 38 | [Bool]$Value = $true 39 | ) 40 | Write-Verbose -Message "In Test-TargetResource" 41 | $false 42 | } 43 | 44 | Export-ModuleMember -Function *-TargetResource 45 | 46 | -------------------------------------------------------------------------------- /tests/integration/targets/win_firewall/tasks/main.yml: -------------------------------------------------------------------------------- 1 | # NOTE: The win_firewall module only works on WMF 5+ 2 | 3 | - ansible.windows.setup: 4 | 5 | - name: Test Windows capabilities 6 | raw: Get-Command Get-NetFirewallProfile -ErrorAction SilentlyContinue; return $? 7 | failed_when: no 8 | register: get_netfirewallprofile 9 | 10 | - name: Only run tests when Windows is capable 11 | when: get_netfirewallprofile.rc == 0 and ansible_powershell_version >= 5 12 | block: 13 | - name: Turn off Windows Firewall (begin) 14 | win_firewall: 15 | profiles: [ Domain, Private, Public ] 16 | state: disabled 17 | register: firewall_off 18 | 19 | - name: Test firewall_off 20 | assert: 21 | that: 22 | - not firewall_off.Domain.enabled 23 | - not firewall_off.Private.enabled 24 | - not firewall_off.Public.enabled 25 | 26 | 27 | - name: Test in normal mode 28 | import_tasks: tests.yml 29 | vars: 30 | in_check_mode: no 31 | 32 | 33 | - name: Test in check-mode 34 | import_tasks: tests.yml 35 | vars: 36 | in_check_mode: yes 37 | check_mode: yes 38 | 39 | 40 | - name: Turn on Windows Firewall (end) 41 | win_firewall: 42 | profiles: [ Domain, Private, Public ] 43 | state: enabled 44 | register: firewall_on 45 | 46 | - name: Test firewall_on 47 | assert: 48 | that: 49 | - firewall_on is changed 50 | - firewall_on.Domain.enabled 51 | - firewall_on.Private.enabled 52 | - firewall_on.Public.enabled 53 | -------------------------------------------------------------------------------- /tests/integration/targets/setup_http_tests/tasks/main.yml: -------------------------------------------------------------------------------- 1 | # The docker --link functionality gives us an ENV var we can key off of to see if we have access to 2 | # the httptester container 3 | - set_fact: 4 | has_httptester: "{{ lookup('env', 'HTTPTESTER') != '' }}" 5 | 6 | - name: If we are running with access to a httptester container, grab it's cacert and install it 7 | when: has_httptester | bool 8 | block: 9 | - name: Override hostname defaults with httptester linked names 10 | include_vars: httptester.yml 11 | 12 | - name: make sure the port forwarder is active 13 | win_wait_for: 14 | host: ansible.http.tests 15 | port: 80 16 | state: started 17 | timeout: 300 18 | 19 | - name: get client cert/key 20 | win_get_url: 21 | url: http://ansible.http.tests/{{ item }} 22 | dest: '{{ remote_tmp_dir }}\{{ item }}' 23 | register: win_download 24 | retries: 5 # Just have a retry in case the host is running a bit slower today. 25 | until: win_download is successful 26 | with_items: 27 | - client.pem 28 | - client.key 29 | 30 | - name: retrieve test cacert 31 | win_get_url: 32 | url: http://ansible.http.tests/cacert.pem 33 | dest: '{{ remote_tmp_dir }}\cacert.pem' 34 | 35 | - name: update ca trust 36 | win_certificate_store: 37 | path: '{{ remote_tmp_dir }}\cacert.pem' 38 | state: present 39 | store_location: LocalMachine 40 | store_name: Root 41 | register: httptester_ca_cert_info 42 | notify: remove CA trust store cert 43 | -------------------------------------------------------------------------------- /tests/integration/targets/win_user_right/library/test_get_right.ps1: -------------------------------------------------------------------------------- 1 | #!powershell 2 | 3 | #Requires -Module Ansible.ModuleUtils.Legacy 4 | 5 | # basic script to get the lsit of users in a particular right 6 | # this is quite complex to put as a simple script so this is 7 | # just a simple module 8 | 9 | $ErrorActionPreference = 'Stop' 10 | 11 | $params = Parse-Args $args -supports_check_mode $false 12 | $name = Get-AnsibleParam -obj $params -name "name" -type "str" -failifempty $true 13 | 14 | $result = @{ 15 | changed = $false 16 | users = @() 17 | } 18 | 19 | Function Get-Username($sid) { 20 | $object = New-Object System.Security.Principal.SecurityIdentifier($sid) 21 | $user = $object.Translate([System.Security.Principal.NTAccount]) 22 | $user.Value 23 | } 24 | 25 | $secedit_ini_path = [IO.Path]::GetTempFileName() 26 | &SecEdit.exe /export /cfg $secedit_ini_path /quiet 27 | $secedit_ini = Get-Content -LiteralPath $secedit_ini_path 28 | Remove-Item -LiteralPath $secedit_ini_path -Force 29 | 30 | foreach ($line in $secedit_ini) { 31 | if ($line.ToLower().StartsWith("$($name.ToLower()) = ")) { 32 | $right_split = $line -split "=" 33 | $existing_users = $right_split[-1].Trim() -split "," 34 | foreach ($user in $existing_users) { 35 | if ($user.StartsWith("*S")) { 36 | $result.users += Get-Username -sid $user.substring(1) 37 | } 38 | else { 39 | $result.users += $user 40 | } 41 | } 42 | } 43 | } 44 | 45 | Exit-Json $result 46 | -------------------------------------------------------------------------------- /tests/integration/targets/win_package/files/reboot.wsx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /tests/integration/targets/win_package/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | test_path: '{{ remote_tmp_dir }}\win_package .ÅÑŚÌβŁÈ [$!@^&test(;)]' 3 | 4 | # MSI packages 5 | good_url: https://ansible-ci-files.s3.amazonaws.com/test/integration/roles/test_win_package/good.msi 6 | reboot_url: https://ansible-ci-files.s3.amazonaws.com/test/integration/roles/test_win_package/reboot.msi 7 | bad_url: https://ansible-ci-files.s3.amazonaws.com/test/integration/roles/test_win_package/bad.msi 8 | 9 | # MSIX tools 10 | makeappx_url: https://ansible-ci-files.s3.amazonaws.com/test/integration/targets/win_package/makeappx.zip 11 | 12 | # MSP packages - https://wixtoolset.org/documentation/manual/v3/patching/patch_building.html 13 | patch_msi_url: https://ansible-ci-files.s3.amazonaws.com/test/integration/targets/win_package/patch.msi 14 | patch_msp_url: https://ansible-ci-files.s3.amazonaws.com/test/integration/targets/win_package/patch.msp 15 | patch_install_file: C:\Program Files (x86)\Patch Sample Directory\Sample.txt 16 | 17 | good_id: '{223D9A13-653B-4231-A365-EDDC30B4F226}' 18 | reboot_id: '{223D9A13-653B-4231-A365-EDDC30B4F227}' 19 | patch_product_id: '{48C49ACE-90CF-4161-9C6E-9162115A54DD}' 20 | patch_patch_id: '{224C316C-5894-4771-BABF-21A3AC1F75FF}' 21 | msix_id: WinPackageMsix 22 | msixbundle_id: WinPackageBundleMsix 23 | appx_id: WinPackageAppx 24 | appxbundle_id: WinPackageBundleAppx 25 | registry_id: WinPackageRegistry 26 | 27 | all_ids: 28 | - '{{ good_id }}' 29 | - '{{ reboot_id }}' 30 | - '{{ patch_product_id }}' 31 | - '{{ msix_id }}' 32 | - '{{ msixbundle_id }}' 33 | - '{{ appx_id }}' 34 | - '{{ appxbundle_id }}' 35 | - '{{ registry_id }}' 36 | -------------------------------------------------------------------------------- /tests/integration/targets/win_optional_feature/tasks/main.yml: -------------------------------------------------------------------------------- 1 | # Test code for win_optional_feature module 2 | # Copyright: (c) 2019, Carson Anderson 3 | 4 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 5 | # 6 | # Ansible is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Ansible is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with Ansible. If not, see . 18 | 19 | - name: check if host supports module 20 | win_shell: if (Get-Command -Name Enable-WindowsOptionalFeature -ErrorAction SilentlyContinue) { $true } else { $false } 21 | register: run_tests 22 | 23 | - name: run tests 24 | when: run_tests.stdout | trim | bool 25 | block: 26 | - name: ensure we start test with removed features 27 | win_optional_feature: 28 | name: 29 | - SimpleTCP 30 | - TelnetClient 31 | state: absent 32 | - include_tasks: tests.yml 33 | 34 | always: 35 | - name: make sure test features have been removed after test 36 | win_optional_feature: 37 | name: 38 | - SimpleTCP 39 | - TelnetClient 40 | state: absent 41 | -------------------------------------------------------------------------------- /tests/unit/conftest.py: -------------------------------------------------------------------------------- 1 | # Copyright: Contributors to the Ansible project 2 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 3 | 4 | """Enable unit testing of Ansible collections. PYTEST_DONT_REWRITE""" 5 | 6 | import os 7 | import os.path 8 | 9 | from ansible.utils.collection_loader._collection_finder import _AnsibleCollectionFinder 10 | 11 | 12 | ANSIBLE_COLLECTIONS_PATH = os.path.abspath(os.path.join(__file__, '..', '..', '..', '..', '..')) 13 | 14 | 15 | # this monkeypatch to _pytest.pathlib.resolve_package_path fixes PEP420 resolution for collections in pytest >= 6.0.0 16 | def collection_resolve_package_path(path): 17 | """Configure the Python package path so that pytest can find our collections.""" 18 | for parent in path.parents: 19 | if str(parent) == ANSIBLE_COLLECTIONS_PATH: 20 | return parent 21 | 22 | raise Exception('File "%s" not found in collection path "%s".' % (path, ANSIBLE_COLLECTIONS_PATH)) 23 | 24 | 25 | def pytest_configure(): 26 | """Configure this pytest plugin.""" 27 | 28 | try: 29 | if pytest_configure.executed: 30 | return 31 | except AttributeError: 32 | pytest_configure.executed = True 33 | 34 | # allow unit tests to import code from collections 35 | 36 | # noinspection PyProtectedMember 37 | _AnsibleCollectionFinder(paths=[os.path.dirname(ANSIBLE_COLLECTIONS_PATH)])._install() # pylint: disable=protected-access 38 | 39 | # noinspection PyProtectedMember 40 | from _pytest import pathlib as pytest_pathlib 41 | pytest_pathlib.resolve_package_path = collection_resolve_package_path 42 | 43 | 44 | pytest_configure() 45 | -------------------------------------------------------------------------------- /plugins/modules/win_feature_info.ps1: -------------------------------------------------------------------------------- 1 | #!powershell 2 | 3 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | #AnsibleRequires -CSharpUtil Ansible.Basic 5 | 6 | $spec = @{ 7 | options = @{ 8 | name = @{ type = "str"; default = '*' } 9 | } 10 | supports_check_mode = $true 11 | } 12 | 13 | $module = [Ansible.Basic.AnsibleModule]::Create($args, $spec) 14 | 15 | $name = $module.Params.name 16 | 17 | $module.Result.exists = $false 18 | 19 | $features = Get-WindowsFeature -Name $name 20 | 21 | $module.Result.features = @(foreach ($feature in ($features)) { 22 | # These should closely reflect the options for win_feature 23 | @{ 24 | name = $feature.Name 25 | display_name = $feature.DisplayName 26 | description = $feature.Description 27 | installed = $feature.Installed 28 | install_state = $feature.InstallState.ToString() 29 | feature_type = $feature.FeatureType 30 | path = $feature.Path 31 | depth = $feature.Depth 32 | depends_on = $feature.DependsOn 33 | parent = $feature.Parent 34 | server_component_descriptor = $feature.ServerComponentDescriptor 35 | sub_features = $feature.SubFeatures 36 | system_service = $feature.SystemService 37 | best_practices_model_id = $feature.BestPracticesModelId 38 | event_query = $feature.EventQuery 39 | post_configuration_needed = $feature.PostConfigurationNeeded 40 | additional_info = $feature.AdditionalInfo 41 | } 42 | $module.Result.exists = $true 43 | }) 44 | 45 | $module.ExitJson() 46 | -------------------------------------------------------------------------------- /tests/integration/targets/win_acl_inheritance/library/test_get_acl.ps1: -------------------------------------------------------------------------------- 1 | #!powershell 2 | 3 | # WANT_JSON 4 | # POWERSHELL_COMMON 5 | 6 | $ErrorActionPreference = 'Stop' 7 | Set-StrictMode -Version 2.0 8 | 9 | $params = Parse-Args $args -supports_check_mode $false 10 | $path = Get-AnsibleParam -obj $params 'path' -type 'str' -failifempty $true 11 | 12 | $result = @{ 13 | changed = $false 14 | } 15 | 16 | if (-not $path.StartsWith('\\?\')) { 17 | $path = [System.Environment]::ExpandEnvironmentVariables($path) 18 | } 19 | 20 | $regeditHives = @{ 21 | 'HKCR' = 'HKEY_CLASSES_ROOT' 22 | 'HKU' = 'HKEY_USERS' 23 | 'HKCC' = 'HKEY_CURRENT_CONFIG' 24 | } 25 | 26 | $pathQualifier = Split-Path -Path $path -Qualifier -ErrorAction SilentlyContinue 27 | $pathQualifier = $pathQualifier.Replace(':', '') 28 | 29 | if ($pathQualifier -in $regeditHives.Keys -and (-not (Test-Path -LiteralPath "${pathQualifier}:\"))) { 30 | $null = New-PSDrive -Name $pathQualifier -PSProvider 'Registry' -Root $regeditHives.$pathQualifier 31 | Push-Location -LiteralPath "${pathQualifier}:\" 32 | } 33 | 34 | $acl = Get-Acl -LiteralPath $path 35 | 36 | $result.inherited = $acl.AreAccessRulesProtected -eq $false 37 | 38 | $user_details = @{} 39 | $acl.Access | ForEach-Object { 40 | $user = $_.IdentityReference.Translate([System.Security.Principal.SecurityIdentifier]).Value 41 | if ($user_details.ContainsKey($user)) { 42 | $details = $user_details.$user 43 | } 44 | else { 45 | $details = @{ 46 | isinherited = $false 47 | } 48 | } 49 | $details.isinherited = $_.IsInherited 50 | $user_details.$user = $details 51 | } 52 | 53 | $result.user_details = $user_details 54 | 55 | Exit-Json $result 56 | -------------------------------------------------------------------------------- /plugins/modules/slurp.yml: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022 Ansible Project 2 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 3 | 4 | DOCUMENTATION: 5 | module: slurp 6 | short_description: Slurps a file from remote nodes 7 | description: 8 | - This module works like M(ansible.builtin.fetch). It is used for fetching a base64- 9 | encoded blob containing the data in a remote file. 10 | options: 11 | src: 12 | description: 13 | - The file on the remote system to fetch. This I(must) be a file, not a directory. 14 | type: path 15 | required: true 16 | aliases: [path] 17 | notes: 18 | - This module returns an 'in memory' base64 encoded version of the file, take 19 | into account that this will require at least twice the RAM as the original file size. 20 | seealso: 21 | - module: ansible.builtin.fetch 22 | - module: ansible.builtin.slurp 23 | author: 24 | - Ansible Core Team 25 | 26 | EXAMPLES: | 27 | - name: Retrieve remote ini file on a Windows host 28 | ansible.windows.slurp: 29 | src: C:\Program Files\Program\program.ini 30 | register: program_conf 31 | 32 | - name: Print returned information 33 | ansible.builtin.debug: 34 | msg: "{{ program_conf['content'] | b64decode }}" 35 | 36 | RETURN: 37 | content: 38 | description: Encoded file content 39 | returned: success 40 | type: str 41 | sample: "MjE3OQo=" 42 | encoding: 43 | description: Type of encoding used for file 44 | returned: success 45 | type: str 46 | sample: "base64" 47 | source: 48 | description: Actual path of file slurped 49 | returned: success 50 | type: str 51 | sample: C:\Program Files\Program\program.ini 52 | -------------------------------------------------------------------------------- /tests/integration/targets/win_service/tasks/pre_shutdown_timeout_ms.yml: -------------------------------------------------------------------------------- 1 | - name: set pre shutdown timeout ms (check) 2 | win_service: 3 | name: '{{ test_win_service_name }}' 4 | pre_shutdown_timeout_ms: 0xFFFFFFFF 5 | register: set_pre_shutdown_timeout_ms_check 6 | check_mode: yes 7 | 8 | - name: get result of set pre shutdown timeout ms (check) 9 | win_service_info: 10 | name: '{{ test_win_service_name }}' 11 | register: set_pre_shutdown_timeout_ms_actual_check 12 | 13 | - name: assert set pre shutdown timeout ms (check) 14 | assert: 15 | that: 16 | - set_pre_shutdown_timeout_ms_check is changed 17 | # Different OS versions have different defaults, just make sure it didn't set our value in check mode 18 | - set_pre_shutdown_timeout_ms_actual_check.services[0].pre_shutdown_timeout_ms != 4294967295 19 | 20 | - name: set pre shutdown timeout ms 21 | win_service: 22 | name: '{{ test_win_service_name }}' 23 | pre_shutdown_timeout_ms: 0xFFFFFFFF 24 | register: set_type 25 | 26 | - name: get result of set pre shutdown timeout ms 27 | win_service_info: 28 | name: '{{ test_win_service_name }}' 29 | register: set_pre_shutdown_timeout_ms_actual 30 | 31 | - name: assert set pre shutdown timeout ms 32 | assert: 33 | that: 34 | - set_type is changed 35 | - set_pre_shutdown_timeout_ms_actual.services[0].pre_shutdown_timeout_ms == 4294967295 36 | 37 | - name: set pre shutdown timeout ms (idempotent) 38 | win_service: 39 | name: '{{ test_win_service_name }}' 40 | pre_shutdown_timeout_ms: 0xFFFFFFFF 41 | register: set_pre_shutdown_timeout_ms_again 42 | 43 | - name: assert set pre shutdown timeout ms (idempotent) 44 | assert: 45 | that: 46 | - not set_pre_shutdown_timeout_ms_again is changed 47 | -------------------------------------------------------------------------------- /plugins/modules/win_route.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright: (c) 2025, Red Hat, Inc. 5 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 6 | 7 | DOCUMENTATION = r''' 8 | --- 9 | module: win_route 10 | short_description: Add or remove a static route 11 | description: 12 | - Add or remove a static route. 13 | version_added: 2.7.0 14 | options: 15 | destination: 16 | description: 17 | - Destination IP address in CIDR format (ip address/prefix length). 18 | type: str 19 | required: yes 20 | gateway: 21 | description: 22 | - The gateway used by the static route. 23 | - If C(gateway) is not provided it will be set to C(0.0.0.0). 24 | type: str 25 | default: 0.0.0.0 26 | metric: 27 | description: 28 | - Metric used by the static route. 29 | type: int 30 | default: 1 31 | state: 32 | description: 33 | - If C(absent), it removes a network static route. 34 | - If C(present), it adds a network static route. 35 | type: str 36 | choices: [ absent, present ] 37 | default: present 38 | notes: 39 | - Works only with Windows 2012 R2 and newer. 40 | author: 41 | - Amit Weinstock (@amitosw15) 42 | ''' 43 | 44 | EXAMPLES = r''' 45 | --- 46 | - name: Add a network static route 47 | ansible.windows.win_route: 48 | destination: 192.168.2.10/32 49 | gateway: 192.168.1.1 50 | metric: 1 51 | state: present 52 | 53 | - name: Remove a network static route 54 | ansible.windows.win_route: 55 | destination: 192.168.2.10/32 56 | state: absent 57 | ''' 58 | RETURN = r''' 59 | msg: 60 | description: A message describing the task result. 61 | returned: always 62 | type: str 63 | sample: "Route added" 64 | ''' 65 | -------------------------------------------------------------------------------- /tests/integration/targets/win_certificate_store/files/root-key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpAIBAAKCAQEAyaphPx5ljqsVAqeZJxQaedQfW0tD7dZCl8qJbKAJRJvUI2o7 3 | cnW7ekYwSpgznwsrgqsymyS/srW0JX8QxmoZOpcAh9IvL26aVv/0LcCEv22EE+fk 4 | j11qb8SashmS0j3/DljAFefi2h746ikDdCQxCH0FSNQI9v1904j6Kvs4YVkybFea 5 | Izrj4ER7LAzahIax1n3mFTfvxQG7Yhfj44BXwVuvaXpVb4XGD+0og6joGzjo9rgR 6 | mC16Y6qzeTFgE6W0FNu8VwuwtrgphW7kZ7lh8HQDF9p6bs+g/wiUyzyDHKiNn+vS 7 | jmHPFRxiUv+HwZ56gtY8UV2IBL5SDFYg06o1cwIDAQABAoIBAFRpZNsutgPJyLmb 8 | vZeF6q8kAxwLnRtom+c9d9hoBHkbYOiSBuAaN6cuyffvTWw9GLFRR5V5BGSheg5X 9 | 6YWj03uayTYQ3H9WJHRWHrcn5mjaRnaukhUQXQT7nmT+H16xZJl0vLJupZ33aOla 10 | 0X9DxuJusk+RsU7xPEHXDCABl8/m7v3cFttUBughGBG5oDuzKlFbhXPwA8/yeJ1v 11 | qdXKxENi9HO4X5fH1l0vFNIhEqvUVKjw/AzapYtr+bv1wssoNAzvhT7CFa2GjPQ0 12 | Ibcq3+RxyAN4iQVITy86Yl4LW1jLx63wbg9q1WG/ca9K/OEAuT7ebJNeMYmM+kf7 13 | sf6A8wECgYEA+nnLJ4QtANtAs6nmDC106DTx1cOf3Yq9JOAvmGLomF/8SrUzZbXM 14 | F+JcZcttXuuFIFcZD0K7fFP9sx2ITH//BS5V0B0x7Z2olWexVjR6/5pOVFPu19ow 15 | tyDCNi5BlTPbvSr/fAxjmO9SgVTb8oG66i4mi0Xn5bp1E441KdvNsHECgYEAzhz/ 16 | +SjFJlJcGNvMmgfAbfv6McUv7TKrPIvVkA++Gi5QdqJjkuzL1uTfgWIY/9iDByMd 17 | W36rFTkYrw6LTMF2dkMjul72Kkco3UExSzOmF4lFmCt3DZW6a6CExKpwk4kF2RnX 18 | GRD0FoZZown3RbPHi9rsWxjyVy/yKGwnvXYndiMCgYEA6rnIUDfllK/jansFQtQ2 19 | goVbPGAfKJYjurL852mJX4JUBA7bI63CnX9b52lEDXfZQf1dVpfK6zAqx/gdCtPI 20 | QSqy8FzrtSnSGnEaFxcHTRFl5lDhuxaWIIdqeSvP+eqnOhdZZP6XN3LPdrP3isNY 21 | Tq0BIfNY5khd/v19hMSfdYECgYBQ8h6tMY/LrwiwUpIV4/l0uELYDQL3erC5RImI 22 | 3EXiblH3ZWsJpqmfKZ+FZos+3z8GLIo5BpQV76h8B5A5grkNVOzRIr42eF/aFOJR 23 | EGWoVKbaTiehVC40WoQJ4I35wxRi4L0TAQ97USQe3akY3LP/fujYFgIGr7PAoEkz 24 | JRX2VQKBgQDir8/a3FZVo6nYI8zIhBz8xqZJIgvlYQqiQFFwADu5eNPMvNIaVy+6 25 | 7HKibGM2jPkuS2KHdc8WUp8IrRRMui04qE7kRxVu41QXEBfPiDvrvAQf8SfJe631 26 | XvYeZr7HKY4NI5J0ENcb54d7DLQ8a1/wL/GeLVrfUWG35Ra5MW57Og== 27 | -----END RSA PRIVATE KEY----- 28 | 29 | -------------------------------------------------------------------------------- /tests/integration/targets/win_certificate_store/files/subj-key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpAIBAAKCAQEA7M6nRUqNxpVT9cVJzeG0j6xURYjpfzKrqdGZ+VCSVEfcC50Q 3 | /ji3Ku5Cop+oWKqM0ru3AvgZ1kKKu7xkkjVar+wahTMMxibfSAVEL9FKiEJAP3bl 4 | HSnQIjJ9j0EbDQ55FhG04+MbIrSLVTb/OHAxtJZGQWMk4H8mZWS2VqZZKVEJK2Ya 5 | BQnpGUSfjg66jVt1uetK6zlCIfh4kHgaqHGrejncYCAgaqVIfBFaNYoWtw14xjdP 6 | KubrYOoJmyJdlQWlSY38ncJ1Eqh8pScIelgiBIfh17J+J3XzVkjf3w6r4uSNdFdY 7 | +maLO8qkH/KgHs1AJunkqoS4Gc9KHavQ7DuBxwIDAQABAoIBAQDfjqBfS+jYZrUi 8 | uqPYV5IMaNYN5xj4Wi+xXA0OT0A1jLlxxU/7kDNrtg72U9+sBSZ483nstag+nAc5 9 | ALu5Q+FfX3gR84XFs4DrDv22XtEMHe9leqsFgynYfu4GRaJyCw3JBeJNmWNOuj8n 10 | rYn4EAL8xzmAFUcFIURwSEnTN6vI0cS09nQukz+9CIBuGr7TPMET8YlATDJcH+Ua 11 | EGZ9MAFXdKF6adC2nrCVBDNr8mUEpK1XdQcPH2bvcTuZ3Jj5AF2rOrcHq4FZUm97 12 | 8PaMH6Sarxhwl+ycwrKbU5aEzUYTk67k0V6m9lyvH9z3O3Y84Tr3cZZ5WxdnG6Ri 13 | 72MFlfgRAoGBAP8wA+KWJ/ttmEXAoSX4J2fPl7X1RhR+1zPNdLY7iX0uNstL8IFH 14 | vUN9JHi1Tr7llav+2bUTOu2EMDVmDWZH0s/qKOn+GmqIQLp0441fVAiamTcgwGKE 15 | Wwsu4dg10IJ9akHIIbrILT0CvRcIRf67EYLBj3ZwfR+wF1ncefbsxWA9AoGBAO2P 16 | qGMn+yrIi5DZF23x6iD2Y7bIdlUmqIqwb99XhW+3YJmRuh1EuN6XP2bIveRa9xvm 17 | Q7bbcQM0Yv2c7eTyxpzz2I4bmnccVbs6M1VhtkyQEy5+X5yOl9wnitaaUrbWFy/w 18 | kDPuISjLl3xDlxd6dbjf70fkG5oogx5c5toEyWZTAoGAK1CHGErMdozfr9dGgx9f 19 | 8Or3oVcEki4FcTGKgfQRHkJd4pv9MrRul6oCKsr7lsN5aDxVz7p34iDx3d54n8fJ 20 | LKleUHllGngOJJf6l+B6bwtuvkC85vv4SCmpA/3+amfHRWsm7oFTzGtOlT4+Q0KV 21 | clBQfZYSZvKIxCP8P8ForzECgYEAjDOad1qjOy68X7Ifx71cJjQDyV4pqDt2gNN8 22 | Ut1+XN5m3ntI0fk6+fNdcbXLjDe7WvXcxNBhtDh4q6CwLcyyNvMavVPBJ8bLOgIx 23 | RZSzWCA3kdr3ZpgpO78Ci4DsjAdyC9L36A4D9+Wf87CYPT0CuSdAOrd/Ks36BDNj 24 | 8wucKQ0CgYAaRwQ18nkemrpQ/+EQgEWnWfqgB+6T4ygZ4ZTym0FAtG7CdLxvCi8V 25 | toyn+zi+yFTRFXHDmvg9HLIIMK/hRQjgc8Ns5nDwgQlGwCZTvjVbD4anCr1IWuky 26 | owvxKWsHseNilKrnAk2maQxrrrpSk8QWrp2CFw04LsWGTxtFvstBmg== 27 | -----END RSA PRIVATE KEY----- 28 | 29 | -------------------------------------------------------------------------------- /tests/integration/targets/win_feature_info/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: test we can get info for all features 3 | win_feature_info: 4 | register: all_actual 5 | check_mode: yes # tests that this will run in check mode 6 | 7 | - name: assert test we can get info for all features 8 | assert: 9 | that: 10 | - all_actual.exists 11 | - not all_actual is changed 12 | 13 | - name: test info on a missing feature 14 | win_feature_info: 15 | name: ansible_feature_info_missing 16 | register: missing_feature 17 | 18 | - name: assert test info on a missing feature 19 | assert: 20 | that: 21 | - not missing_feature is changed 22 | - not missing_feature.exists 23 | 24 | - name: Install Test Feature 25 | ansible.windows.win_feature: 26 | name: "{{ test_feature }}" 27 | state: present 28 | 29 | - name: test info on a single Feature 30 | win_feature_info: 31 | name: '{{ test_feature }}' 32 | register: specific_feature_present 33 | 34 | - name: assert test info on single feature 35 | assert: 36 | that: 37 | - not specific_feature_present is changed 38 | - specific_feature_present.exists 39 | - specific_feature_present.features | length == 1 40 | - specific_feature_present.features[0].install_state == "Installed" 41 | 42 | - name: Uninstall Test Feature 43 | ansible.windows.win_feature: 44 | name: "{{ test_feature }}" 45 | state: absent 46 | 47 | - name: test info on a single Feature 48 | win_feature_info: 49 | name: '{{ test_feature }}' 50 | register: specific_feature_absent 51 | 52 | - name: assert test info on single feature 53 | assert: 54 | that: 55 | - not specific_feature_absent is changed 56 | - specific_feature_absent.exists 57 | - specific_feature_absent.features | length == 1 58 | - specific_feature_absent.features[0].install_state == "Available" 59 | -------------------------------------------------------------------------------- /plugins/modules/win_product_facts.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright: (c) 2017, Dag Wieers (@dagwieers) 5 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 6 | 7 | DOCUMENTATION = r''' 8 | --- 9 | module: win_product_facts 10 | short_description: Provides Windows product and license information 11 | description: 12 | - Provides Windows product and license information. 13 | version_added: 2.7.0 14 | author: 15 | - Dag Wieers (@dagwieers) 16 | ''' 17 | 18 | EXAMPLES = r''' 19 | - name: Get product id and product key 20 | ansible.windows.win_product_facts: 21 | 22 | - name: Display Windows edition 23 | debug: 24 | var: ansible_os_license_edition 25 | 26 | - name: Display Windows license status 27 | debug: 28 | var: ansible_os_license_status 29 | ''' 30 | 31 | RETURN = r''' 32 | ansible_facts: 33 | description: Dictionary containing all the detailed information about the Windows product and license. 34 | returned: always 35 | type: complex 36 | contains: 37 | ansible_os_license_channel: 38 | description: The Windows license channel. 39 | returned: always 40 | type: str 41 | sample: Volume:MAK 42 | ansible_os_license_edition: 43 | description: The Windows license edition. 44 | returned: always 45 | type: str 46 | sample: Windows(R) ServerStandard edition 47 | ansible_os_license_status: 48 | description: The Windows license status. 49 | returned: always 50 | type: str 51 | sample: Licensed 52 | ansible_os_product_id: 53 | description: The Windows product ID. 54 | returned: always 55 | type: str 56 | sample: 00326-10000-00000-AA698 57 | ansible_os_product_key: 58 | description: The Windows product key. 59 | returned: always 60 | type: str 61 | sample: T49TD-6VFBW-VV7HY-B2PXY-MY47H 62 | ''' 63 | -------------------------------------------------------------------------------- /tests/integration/targets/win_hostname/tasks/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: fail to set hostname to an invalid name 3 | win_hostname: 4 | name: invalid/name 5 | register: fail_hostname 6 | failed_when: '"Failed to rename computer to ''invalid/name''" not in fail_hostname.msg' 7 | 8 | - name: change the hostname (check) 9 | win_hostname: 10 | name: '{{test_win_hostname_name}}' 11 | register: change_hostname_check 12 | check_mode: yes 13 | 14 | - name: get actual hostname 15 | win_shell: $env:COMPUTERNAME 16 | register: change_hostname_actual_check 17 | 18 | - name: assert change the hostname (check) 19 | assert: 20 | that: 21 | - change_hostname_check is changed 22 | - change_hostname_check.old_name|upper != test_win_hostname_name|upper 23 | - change_hostname_check.reboot_required 24 | - change_hostname_actual_check.stdout_lines[0]|upper != test_win_hostname_name|upper 25 | 26 | - name: change the hostname 27 | win_hostname: 28 | name: '{{test_win_hostname_name}}' 29 | register: change_hostname 30 | 31 | - name: reboot after changing the hostname 32 | win_reboot: 33 | 34 | - name: get actual hostname 35 | win_shell: $env:COMPUTERNAME 36 | register: change_hostname_actual 37 | 38 | - name: assert change the hostname 39 | assert: 40 | that: 41 | - change_hostname is changed 42 | - change_hostname.old_name|upper == change_hostname_check.old_name|upper 43 | - change_hostname.reboot_required 44 | - change_hostname_actual.stdout_lines[0]|upper == test_win_hostname_name|upper 45 | 46 | - name: change the hostname (idempotent) 47 | win_hostname: 48 | name: '{{test_win_hostname_name}}' 49 | register: change_hostname_again 50 | 51 | - name: assert change the hostname (idempotent) 52 | assert: 53 | that: 54 | - not change_hostname_again is changed 55 | - change_hostname_again.old_name|upper == test_win_hostname_name|upper 56 | - not change_hostname_again.reboot_required 57 | -------------------------------------------------------------------------------- /docs/docsite/links.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # based on https://github.com/ansible-collections/collection_template/blob/main/docs/docsite/links.yml 3 | # 4 | # This will make sure that plugin and module documentation gets Edit on GitHub links 5 | # that allow users to directly create a PR for this plugin or module in GitHub's UI. 6 | # Remove this section if the collection repository is not on GitHub, or if you do not want this 7 | # functionality for your collection. 8 | edit_on_github: 9 | repository: ansible-collections/ansible.windows 10 | branch: main 11 | # If your collection root (the directory containing galaxy.yml) does not coincide with your 12 | # repository's root, you have to specify the path to the collection root here. For example, 13 | # if the collection root is in a subdirectory ansible_collections/community/REPO_NAME 14 | # in your repository, you have to set path_prefix to 'ansible_collections/community/REPO_NAME'. 15 | path_prefix: '' 16 | 17 | # Here you can add arbitrary extra links. Please keep the number of links down to a 18 | # minimum! Also please keep the description short, since this will be the text put on 19 | # a button. 20 | # 21 | # Also note that some links are automatically added from information in galaxy.yml. 22 | # The following are automatically added: 23 | # 1. A link to the issue tracker (if `issues` is specified); 24 | # 2. A link to the homepage (if `homepage` is specified and does not equal the 25 | # `documentation` or `repository` link); 26 | # 3. A link to the collection's repository (if `repository` is specified). 27 | 28 | # extra_links: 29 | # - description: 30 | # url: 31 | 32 | # Specify communication channels for your collection. We suggest to not specify more 33 | # than one place for communication per communication tool to avoid confusion. 34 | communication: 35 | forum: 36 | - topic: Windows automation usage and support questions 37 | url: https://forum.ansible.com/tag/windows 38 | -------------------------------------------------------------------------------- /plugins/modules/win_tempfile.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # coding: utf-8 -*- 3 | 4 | # Copyright: (c) 2017, Dag Wieers 5 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 6 | 7 | DOCUMENTATION = r''' 8 | --- 9 | module: win_tempfile 10 | short_description: Creates temporary files and directories 11 | description: 12 | - Creates temporary files and directories. 13 | - For non-Windows targets, please use the M(ansible.builtin.tempfile) module instead. 14 | options: 15 | state: 16 | description: 17 | - Whether to create file or directory. 18 | type: str 19 | choices: [ directory, file ] 20 | default: file 21 | path: 22 | description: 23 | - Location where temporary file or directory should be created. 24 | - If path is not specified default system temporary directory (%TEMP%) will be used. 25 | type: path 26 | default: '%TEMP%' 27 | aliases: [ dest ] 28 | prefix: 29 | description: 30 | - Prefix of file/directory name created by module. 31 | type: str 32 | default: ansible. 33 | suffix: 34 | description: 35 | - Suffix of file/directory name created by module. 36 | type: str 37 | seealso: 38 | - module: ansible.builtin.tempfile 39 | author: 40 | - Dag Wieers (@dagwieers) 41 | ''' 42 | 43 | EXAMPLES = r""" 44 | - name: Create temporary build directory 45 | ansible.windows.win_tempfile: 46 | state: directory 47 | suffix: build 48 | 49 | - name: Create temporary file with custom prefix 50 | ansible.windows.win_tempfile: 51 | state: file 52 | prefix: customlog_ 53 | 54 | - name: Create temporary file 55 | ansible.windows.win_tempfile: 56 | state: file 57 | suffix: temp 58 | """ 59 | 60 | RETURN = r''' 61 | path: 62 | description: The absolute path to the created file or directory. 63 | returned: success 64 | type: str 65 | sample: C:\Users\Administrator\AppData\Local\Temp\ansible.bMlvdk 66 | ''' 67 | -------------------------------------------------------------------------------- /tests/integration/targets/win_credential/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: ensure test dir is present 3 | ansible.windows.win_file: 4 | path: '{{ test_credential_dir }}' 5 | state: directory 6 | 7 | - name: copy the pfx certificate 8 | ansible.windows.win_copy: 9 | src: cert.pfx 10 | dest: '{{ test_credential_dir }}\cert.pfx' 11 | 12 | - name: import the pfx into the personal store 13 | ansible.windows.win_certificate_store: 14 | path: '{{ test_credential_dir }}\cert.pfx' 15 | state: present 16 | store_location: CurrentUser 17 | store_name: My 18 | password: '{{ key_password }}' 19 | vars: &become_vars 20 | ansible_become: True 21 | ansible_become_method: runas 22 | ansible_become_user: '{{ ansible_user }}' 23 | ansible_become_pass: '{{ ansible_password | default(ansible_test_connection_password) }}' 24 | 25 | - name: ensure test credentials are removed before testing 26 | win_credential: 27 | name: '{{ test_hostname }}' 28 | type: '{{ item }}' 29 | state: absent 30 | vars: *become_vars 31 | with_items: 32 | - domain_password 33 | - domain_certificate 34 | - generic_password 35 | - generic_certificate 36 | 37 | - block: 38 | - name: run tests 39 | include_tasks: tests.yml 40 | 41 | always: 42 | - name: remove the pfx from the personal store 43 | ansible.windows.win_certificate_store: 44 | state: absent 45 | thumbprint: '{{ cert_thumbprint }}' 46 | store_location: CurrentUser 47 | store_name: My 48 | 49 | - name: remove test credentials 50 | win_credential: 51 | name: '{{ test_hostname }}' 52 | type: '{{ item }}' 53 | state: absent 54 | vars: *become_vars 55 | with_items: 56 | - domain_password 57 | - domain_certificate 58 | - generic_password 59 | - generic_certificate 60 | 61 | - name: remove test dir 62 | ansible.windows.win_file: 63 | path: '{{ test_credential_dir }}' 64 | state: absent 65 | -------------------------------------------------------------------------------- /plugins/modules/win_computer_description.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright: (c) 2019, RusoSova 5 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 6 | 7 | DOCUMENTATION = r''' 8 | --- 9 | module: win_computer_description 10 | short_description: Set windows description, owner and organization 11 | description: 12 | - This module sets Windows description that is shown under My Computer properties. Module also sets 13 | Windows license owner and organization. License information can be viewed by running winver commad. 14 | version_added: 2.7.0 15 | options: 16 | description: 17 | description: 18 | - String value to apply to Windows descripton. Specify value of "" to clear the value. 19 | required: false 20 | type: str 21 | organization: 22 | description: 23 | - String value of organization that the Windows is licensed to. Specify value of "" to clear the value. 24 | required: false 25 | type: str 26 | owner: 27 | description: 28 | - String value of the persona that the Windows is licensed to. Specify value of "" to clear the value. 29 | required: false 30 | type: str 31 | author: 32 | - RusoSova (@RusoSova) 33 | ''' 34 | 35 | EXAMPLES = r''' 36 | - name: Set Windows description, owner and organization 37 | ansible.windows.win_computer_description: 38 | description: Best Box 39 | owner: RusoSova 40 | organization: MyOrg 41 | register: result 42 | 43 | - name: Set Windows description only 44 | ansible.windows.win_computer_description: 45 | description: This is my Windows machine 46 | register: result 47 | 48 | - name: Set organization and clear owner field 49 | ansible.windows.win_computer_description: 50 | owner: '' 51 | organization: Black Mesa 52 | 53 | - name: Clear organization, description and owner 54 | ansible.windows.win_computer_description: 55 | organization: "" 56 | owner: "" 57 | description: "" 58 | register: result 59 | ''' 60 | 61 | RETURN = r''' 62 | # 63 | ''' 64 | -------------------------------------------------------------------------------- /tests/integration/targets/win_service/tasks/load_order_group.yml: -------------------------------------------------------------------------------- 1 | - name: set load order group (check) 2 | win_service: 3 | name: '{{ test_win_service_name }}' 4 | load_order_group: order group 5 | register: set_load_order_group_check 6 | check_mode: yes 7 | 8 | - name: get result of set load order group (check) 9 | win_service_info: 10 | name: '{{ test_win_service_name }}' 11 | register: set_load_order_group_actual_check 12 | 13 | - name: assert set load order group (check) 14 | assert: 15 | that: 16 | - set_load_order_group_check is changed 17 | - set_load_order_group_actual_check.services[0].load_order_group == '' 18 | 19 | - name: set load order group 20 | win_service: 21 | name: '{{ test_win_service_name }}' 22 | load_order_group: order group 23 | register: set_type 24 | 25 | - name: get result of set load order group 26 | win_service_info: 27 | name: '{{ test_win_service_name }}' 28 | register: set_load_order_group_actual 29 | 30 | - name: assert set load order group 31 | assert: 32 | that: 33 | - set_type is changed 34 | - set_load_order_group_actual.services[0].load_order_group == 'order group' 35 | 36 | - name: set load order group (idempotent) 37 | win_service: 38 | name: '{{ test_win_service_name }}' 39 | load_order_group: order group 40 | register: set_load_order_group_again 41 | 42 | - name: assert set load order group (idempotent) 43 | assert: 44 | that: 45 | - not set_load_order_group_again is changed 46 | 47 | - name: reset load order group 48 | win_service: 49 | name: '{{ test_win_service_name }}' 50 | load_order_group: '' 51 | register: reset_load_order_group 52 | 53 | - name: get result of reset load order group 54 | win_service_info: 55 | name: '{{ test_win_service_name }}' 56 | register: reset_load_order_group_actual 57 | 58 | - name: assert reset load order group 59 | assert: 60 | that: 61 | - reset_load_order_group is changed 62 | - reset_load_order_group_actual.services[0].load_order_group == '' 63 | -------------------------------------------------------------------------------- /plugins/filter/quote.yml: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022 Ansible Project 2 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 3 | 4 | DOCUMENTATION: 5 | name: quote 6 | author: 7 | - Jordan Borean (@jborean93) 8 | short_description: Quotes argument(s) for various Windows shells 9 | seealso: 10 | - module: ansible.windows.win_command 11 | - module: ansible.windows.win_shell 12 | description: 13 | - Quotes argument(s) for the various Windows command line shells. 14 | - Defaults to escaping arguments based on the Win32 C argv parsing rules that M(ansible.windows.win_command) uses. 15 | - Using I(shell='cmd') or I(shell='powershell') can be set to escape arguments for those respective shells. 16 | - Each value is escaped in a way to ensure the process gets the literal argument passed in and meta chars escaped. 17 | positional: _input 18 | options: 19 | _input: 20 | description: 21 | - The string, list, or dict of values to quote. 22 | - A string or list of strings will be quoted. 23 | - When using a dict as the input, the final form will be in C(KEY="value") to match the MSI parameter format. 24 | type: raw 25 | required: true 26 | shell: 27 | description: 28 | - The shell to quote the arguments for. 29 | - By default no shell is used and the arguments are quoted with the Win32 C quoting rules. 30 | type: string 31 | choices: 32 | - None 33 | - cmd 34 | - powershell 35 | default: None 36 | 37 | EXAMPLES: | 38 | - name: Escape an argument for win_command 39 | ansible.windows.win_command: 40 | cmd: my.exe {{ argument1 | ansible.windows.quote }} 41 | 42 | - name: Escape an argument for PowerShell 43 | ansible.windows.win_shell: | 44 | $var = {{ argument1 | ansible.windows.quote(shell='powershell') }} 45 | Write-Host $var 46 | 47 | RETURN: 48 | _value: 49 | description: 50 | - The quoted input value(s) as a single space delimited string. 51 | type: string 52 | -------------------------------------------------------------------------------- /plugins/modules/win_computer_description.ps1: -------------------------------------------------------------------------------- 1 | #!powershell 2 | 3 | # Copyright: (c) 2019, RusoSova 4 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 5 | 6 | #AnsibleRequires -CSharpUtil Ansible.Basic 7 | #AnsibleRequires -OSVersion 6.1 8 | 9 | $spec = @{ 10 | options = @{ 11 | owner = @{ type = "str" } 12 | organization = @{ type = "str" } 13 | description = @{ type = "str" } 14 | } 15 | required_one_of = @( 16 | , @('owner', 'organization', 'description') 17 | ) 18 | supports_check_mode = $true 19 | } 20 | 21 | $module = [Ansible.Basic.AnsibleModule]::Create($args, $spec) 22 | 23 | $owner = $module.Params.owner 24 | $organization = $module.Params.organization 25 | $description = $module.Params.description 26 | $regPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\" 27 | 28 | #Change description 29 | if ($description -or $description -eq "") { 30 | $descriptionObject = Get-CimInstance -class "Win32_OperatingSystem" 31 | if ($description -cne $descriptionObject.description) { 32 | Set-CimInstance -InputObject $descriptionObject -Property @{"Description" = "$description" } -WhatIf:$module.CheckMode 33 | $module.Result.changed = $true 34 | } 35 | } 36 | 37 | #Change owner 38 | if ($owner -or $owner -eq "") { 39 | $curentOwner = (Get-ItemProperty -LiteralPath $regPath -Name RegisteredOwner).RegisteredOwner 40 | if ($curentOwner -cne $owner) { 41 | Set-ItemProperty -LiteralPath $regPath -Name "RegisteredOwner" -Value $owner -WhatIf:$module.CheckMode 42 | $module.Result.changed = $true 43 | } 44 | } 45 | 46 | #Change organization 47 | if ($organization -or $organization -eq "") { 48 | $curentOrganization = (Get-ItemProperty -LiteralPath $regPath -Name RegisteredOrganization).RegisteredOrganization 49 | if ($curentOrganization -cne $organization) { 50 | Set-ItemProperty -LiteralPath $regPath -Name "RegisteredOrganization" -Value $organization -WhatIf:$module.CheckMode 51 | $module.Result.changed = $true 52 | } 53 | } 54 | $module.ExitJson() 55 | -------------------------------------------------------------------------------- /tests/integration/targets/win_hotfix/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: filter servers that can support DISM 3 | ansible.windows.win_command: powershell.exe "Import-Module -Name DISM" 4 | register: eligable_servers 5 | ignore_errors: True 6 | 7 | - name: fail to run module on servers that don't support DISM 8 | win_hotfix: 9 | path: fake 10 | state: present 11 | register: fail_no_dism 12 | failed_when: fail_no_dism.msg != 'The DISM PS module needs to be installed, this can be done through the windows-adk chocolately package' 13 | when: eligable_servers.rc != 0 14 | 15 | - name: run tests on hosts that support DISM 16 | include_tasks: tests.yml 17 | when: eligable_servers.rc == 0 18 | 19 | - name: set output to true if running Server 2012 R2 20 | ansible.windows.win_command: powershell.exe "$version = [Environment]::OSVersion.Version; if ($version.Major -eq 6 -and $version.Minor -eq 3) { 'true' } else { 'false' }" 21 | register: test_hotfix 22 | 23 | - block: 24 | - name: ensure hotfixes are uninstalled before tests 25 | win_hotfix: 26 | hotfix_identifier: '{{item}}' 27 | state: absent 28 | register: pre_uninstall 29 | with_items: 30 | - '{{test_win_hotfix_identifier}}' 31 | - '{{test_win_hotfix_reboot_identifier}}' 32 | 33 | - name: reboot after pre test uninstall if required 34 | ansible.windows.win_reboot: 35 | when: pre_uninstall.results[0].reboot_required == True or pre_uninstall.results[1].reboot_required == True 36 | 37 | - name: run actual hotfix tests on Server 2012 R2 only 38 | include_tasks: tests_2012R2.yml 39 | 40 | always: 41 | - name: ensure hotfixes are uninstalled after tests 42 | win_hotfix: 43 | hotfix_identifier: '{{item}}' 44 | state: absent 45 | register: post_uninstall 46 | with_items: 47 | - '{{test_win_hotfix_identifier}}' 48 | - '{{test_win_hotfix_reboot_identifier}}' 49 | 50 | - name: reboot after post test uninstall if required 51 | ansible.windows.win_reboot: 52 | when: post_uninstall.results[0].reboot_required == True or post_uninstall.results[1].reboot_required == True 53 | 54 | when: test_hotfix.stdout_lines[0] == "true" 55 | -------------------------------------------------------------------------------- /plugins/modules/async_status.ps1: -------------------------------------------------------------------------------- 1 | #!powershell 2 | 3 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 4 | 5 | #Requires -Module Ansible.ModuleUtils.Legacy 6 | 7 | $results = @{ changed = $false } 8 | 9 | $parsed_args = Parse-Args $args -supports_check_mode $true 10 | $jid = Get-AnsibleParam $parsed_args "jid" -failifempty $true -resultobj $results 11 | $mode = Get-AnsibleParam $parsed_args "mode" -Default "status" -ValidateSet "status", "cleanup" 12 | 13 | # parsed in from the async_status action plugin 14 | $async_dir = Get-AnsibleParam $parsed_args "_async_dir" -type "path" -failifempty $true 15 | 16 | $log_path = [System.IO.Path]::Combine($async_dir, $jid) 17 | 18 | If (-not $(Test-Path -LiteralPath $log_path)) { 19 | Fail-Json @{ ansible_job_id = $jid; started = 1; finished = 1 } "could not find job at '$async_dir'" 20 | } 21 | 22 | If ($mode -eq "cleanup") { 23 | Remove-Item -LiteralPath $log_path -Recurse 24 | Exit-Json @{ ansible_job_id = $jid; erased = $log_path } 25 | } 26 | 27 | # NOT in cleanup mode, assume regular status mode 28 | # no remote kill mode currently exists, but probably should 29 | # consider log_path + ".pid" file and also unlink that above 30 | 31 | $data = $null 32 | Try { 33 | $data_raw = Get-Content -LiteralPath $log_path 34 | 35 | # TODO: move this into module_utils/powershell.ps1? 36 | $jss = New-Object System.Web.Script.Serialization.JavaScriptSerializer 37 | $jss.MaxJsonLength = [int]::MaxValue 38 | $data = $jss.DeserializeObject($data_raw) 39 | } 40 | Catch { 41 | If (-not $data_raw) { 42 | # file not written yet? That means it is running 43 | Exit-Json @{ results_file = $log_path; ansible_job_id = $jid; started = 1; finished = 0 } 44 | } 45 | Else { 46 | Fail-Json @{ ansible_job_id = $jid; results_file = $log_path; started = 1; finished = 1 } "Could not parse job output: $data" 47 | } 48 | } 49 | 50 | If (-not $data.ContainsKey("started")) { 51 | $data['finished'] = 1 52 | $data['ansible_job_id'] = $jid 53 | } 54 | ElseIf (-not $data.ContainsKey("finished")) { 55 | $data['finished'] = 0 56 | } 57 | 58 | Exit-Json $data 59 | -------------------------------------------------------------------------------- /tests/integration/targets/win_acl/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: setup test directory 3 | win_file: 4 | path: '{{ test_acl_path }}' 5 | state: directory 6 | 7 | - name: ensure we start with a clean reg path 8 | win_regedit: 9 | path: '{{ test_acl_reg_path }}' 10 | delete_key: yes 11 | state: '{{ item }}' 12 | with_items: 13 | - absent 14 | - present 15 | 16 | - name: create certificates for testing 17 | win_shell: | 18 | $certParams = @{ 19 | KeyAlgorithm = 'RSA' 20 | KeyExportPolicy = 'Exportable' 21 | KeyLength = 2048 22 | } 23 | (New-SelfSignedCertificate @certParams -Subject "ACL Test CNG" -Provider "Microsoft Software Key Storage Provider").Thumbprint 24 | (New-SelfSignedCertificate @certParams -Subject "ACL Test CryptoAPI" -Provider "Microsoft Base Cryptographic Provider v1.0" -KeySpec Signature).Thumbprint 25 | register: test_acl_cert_info 26 | 27 | - name: set variables of certificate thumbprints 28 | set_fact: 29 | test_acl_certificiate_cng_thumbprint: '{{ test_acl_cert_info.stdout_lines[0] }}' 30 | test_acl_certificiate_cryptoapi_thumbprint: '{{ test_acl_cert_info.stdout_lines[1] }}' 31 | 32 | - block: 33 | - name: create test dir for link target 34 | win_file: 35 | path: '{{ test_acl_path }}\target' 36 | state: directory 37 | 38 | - name: create symlinks in test dir 39 | win_powershell: 40 | script: | 41 | param ( 42 | [string]$Path 43 | ) 44 | 45 | cmd.exe /c mklink /J "$Path\junction" "$Path\target" 46 | cmd.exe /c mklink /D "$Path\symlink" "$Path\junction" 47 | parameters: 48 | Path: '{{ test_acl_path }}' 49 | 50 | - name: run tests 51 | include_tasks: tests.yml 52 | 53 | always: 54 | - name: cleanup testing reg path 55 | win_regedit: 56 | path: '{{ test_acl_reg_path }}' 57 | delete_key: yes 58 | state: absent 59 | 60 | - name: uninstall testing certificates 61 | win_certificate_store: 62 | thumbprint: '{{ item }}' 63 | state: absent 64 | store_location: LocalMachine 65 | store_name: My 66 | with_items: 67 | - test_acl_certificiate_cng_thumbprint 68 | - test_acl_certificiate_cryptoapi_thumbprint 69 | -------------------------------------------------------------------------------- /plugins/action/win_powershell.py: -------------------------------------------------------------------------------- 1 | # Copyright: (c) 2025, Ansible Project 2 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 3 | 4 | from __future__ import annotations 5 | 6 | from ansible.errors import AnsibleActionFail 7 | from ansible.module_utils.common.validation import check_type_bool 8 | from ansible.plugins.action import ActionBase 9 | 10 | 11 | class ActionModule(ActionBase): 12 | 13 | def run( 14 | self, 15 | tmp: str | None = None, 16 | task_vars: dict[str, object] | None = None, 17 | ) -> dict[str, object]: 18 | self._supports_async = True 19 | self._supports_check_mode = True 20 | 21 | if task_vars is None: 22 | task_vars = dict() 23 | 24 | result = super(ActionModule, self).run(tmp, task_vars) 25 | del tmp # tmp no longer has any effect 26 | 27 | module_args = self._task.args 28 | path = module_args.get('path', None) 29 | remote_src = check_type_bool(module_args.get('remote_src', False)) 30 | script = module_args.get('script', None) 31 | 32 | if path and not remote_src: 33 | if script: 34 | raise AnsibleActionFail("parameters are mutually exclusive: path, script") 35 | 36 | # Replace the script argument with the contents of the local script. 37 | full_path = self._find_needle('files', path) 38 | module_args['script'] = self._loader.get_text_file_contents(full_path) 39 | del module_args['path'] 40 | 41 | module_result = self._execute_module( 42 | module_name='ansible.windows.win_powershell', 43 | module_args=module_args, 44 | task_vars=task_vars, 45 | wrap_async=self._task.async_val, 46 | ) 47 | if ( 48 | path and not remote_src and 49 | 'invocation' in module_result and 50 | 'module_args' in module_result['invocation'] 51 | ): 52 | # Restores the invocation back to the original state. 53 | module_result['invocation']['module_args']['script'] = None 54 | module_result['invocation']['module_args']['path'] = path 55 | 56 | result.update(module_result) 57 | return result 58 | -------------------------------------------------------------------------------- /tests/integration/targets/win_powershell/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: check if executable is supported 2 | win_shell: '[Version]$PSVersionTable.PSVersion -gt [Version]"5.0"' 3 | register: use_executable 4 | changed_when: False 5 | 6 | - name: get datetimes used for tests 7 | win_shell: | 8 | $epoch_unspec = New-Object -TypeName DateTime -ArgumentList 1970, 1, 1 9 | $epoch_local = New-Object -TypeName DateTime -ArgumentList 1970, 1, 1, 0, 0, 0, ([DateTimeKind]::Local) 10 | $epoch_utc = New-Object -TypeName DateTime -ArgumentList 1970, 1, 1, 0, 0, 0, ([DateTimeKind]::Utc) 11 | 12 | $epoch_unspec.ToString('o') 13 | $epoch_unspec.ToLocalTime().ToString('o') 14 | $epoch_unspec.ToUniversalTime().ToString('o') 15 | 16 | $epoch_local.ToString('o') 17 | $epoch_local.ToLocalTime().ToString('o') 18 | $epoch_local.ToUniversalTime().ToString('o') 19 | 20 | $epoch_utc.ToString('o') 21 | $epoch_utc.ToLocalTime().ToString('o') 22 | $epoch_utc.ToUniversalTime().ToString('o') 23 | 24 | ([DateTimeOffset]$epoch_utc).ToOffset([TimeSpan]::FromHours(2)).ToString('o') 25 | register: dt_values 26 | changed_when: False 27 | 28 | - name: copy across test file 29 | win_copy: 30 | src: test-script.ps1 31 | dest: '{{ remote_tmp_dir }}/test-script.ps1' 32 | 33 | - name: create script with syntax errors 34 | win_copy: 35 | content: | 36 | [- abc 37 | dest: '{{ remote_tmp_dir }}/syntax-error.ps1' 38 | 39 | - name: run failure tests 40 | import_tasks: failure.yml 41 | 42 | - name: run tests using current interpreter 43 | import_tasks: tests.yml 44 | 45 | - name: run tests using executable 46 | import_tasks: tests.yml 47 | when: use_executable.stdout | trim | bool 48 | vars: 49 | pwsh_executable: powershell.exe 50 | 51 | - name: run executable with arguments 52 | win_powershell: 53 | executable: powershell.exe 54 | arguments: 55 | - -ExecutionPolicy 56 | - Restricted 57 | script: | 58 | $env:PSExecutionPolicyPreference 59 | register: exe_with_arguments 60 | when: use_executable.stdout | trim | bool 61 | 62 | - name: assert run executable with arguments 63 | assert: 64 | that: 65 | - exe_with_arguments.output == ['Restricted'] 66 | when: use_executable.stdout | trim | bool 67 | -------------------------------------------------------------------------------- /plugins/modules/win_timezone.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright: (c) 2015, Phil Schwartz 5 | # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 6 | 7 | DOCUMENTATION = r''' 8 | --- 9 | module: win_timezone 10 | short_description: Sets Windows machine timezone 11 | description: 12 | - Sets machine time to the specified timezone. 13 | version_added: 2.6.0 14 | options: 15 | timezone: 16 | description: 17 | - Timezone to set to. 18 | - 'Example: Central Standard Time' 19 | - To disable Daylight Saving time, add the suffix C(_dstoff) on timezones that support this. 20 | type: str 21 | required: yes 22 | notes: 23 | - The module will check if the provided timezone is supported on the machine. 24 | - A list of possible timezones is available from C(tzutil.exe /l) and from 25 | U(https://msdn.microsoft.com/en-us/library/ms912391.aspx) 26 | - If running on Server 2008 the hotfix 27 | U(https://support.microsoft.com/en-us/help/2556308/tzutil-command-line-tool-is-added-to-windows-vista-and-to-windows-server-2008) 28 | needs to be installed to be able to run this module. 29 | seealso: 30 | - module: ansible.windows.win_region 31 | author: 32 | - Phil Schwartz (@schwartzmx) 33 | ''' 34 | 35 | EXAMPLES = r''' 36 | - name: Set timezone to 'Romance Standard Time' (GMT+01:00) 37 | ansible.windows.win_timezone: 38 | timezone: Romance Standard Time 39 | 40 | - name: Set timezone to 'GMT Standard Time' (GMT) 41 | ansible.windows.win_timezone: 42 | timezone: GMT Standard Time 43 | 44 | - name: Set timezone to 'Central Standard Time' (GMT-06:00) 45 | ansible.windows.win_timezone: 46 | timezone: Central Standard Time 47 | 48 | - name: Set timezime to Pacific Standard time and disable Daylight Saving time adjustments 49 | ansible.windows.win_timezone: 50 | timezone: Pacific Standard Time_dstoff 51 | ''' 52 | 53 | RETURN = r''' 54 | previous_timezone: 55 | description: The previous timezone if it was changed, otherwise the existing timezone. 56 | returned: success 57 | type: str 58 | sample: Central Standard Time 59 | timezone: 60 | description: The current timezone (possibly changed). 61 | returned: success 62 | type: str 63 | sample: Central Standard Time 64 | ''' 65 | -------------------------------------------------------------------------------- /tests/integration/targets/win_share/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Run Standard Tests 3 | when: test_win_share 4 | module_defaults: 5 | win_share: 6 | name: "{{ test_win_share_name }}" 7 | path: "{{ test_win_share_path }}" 8 | state: present 9 | block: 10 | - name: Create Standard Test Folder 11 | ansible.windows.win_file: 12 | path: "{{ test_win_share_path }}" 13 | state: directory 14 | 15 | - name: Cleanup Standard Test Share 16 | win_share: &cleanup_std_share 17 | name: "{{ test_win_share_name }}" 18 | state: absent 19 | 20 | - name: Cleanup Standard Root Share 21 | win_share: &cleanup_std_root_share 22 | name: "ROOT_TEST" 23 | state: absent 24 | 25 | - name: Run Standard Tests 26 | ansible.builtin.include_tasks: tests.yml 27 | vars: 28 | _share_name: "{{ test_win_share_name }}" 29 | always: 30 | - name: Cleanup Standard Test Share 31 | win_share: *cleanup_std_share 32 | 33 | - name: Cleanup Standard Root Share 34 | win_share: *cleanup_std_root_share 35 | 36 | - name: Cleanup Standard Test Folder 37 | win_file: 38 | path: "{{ test_win_share_path }}" 39 | state: absent 40 | 41 | - name: Run Cluster Tests 42 | when: test_win_share_cluster 43 | module_defaults: 44 | win_share: 45 | name: "{{ test_win_share_cluster_name }}" 46 | path: "{{ test_win_share_cluster_path }}" 47 | scope_name: "{{ test_win_share_cluster_scope }}" 48 | state: present 49 | block: 50 | - name: Create Cluster Test Folder 51 | ansible.windows.win_file: 52 | path: "{{ test_win_share_cluster_path }}" 53 | state: directory 54 | 55 | - name: Cleanup Cluster Test Share 56 | win_share: &cleanup_cluster_share 57 | name: "{{ test_win_share_cluster_name }}" 58 | state: absent 59 | 60 | - name: Run Cluster Tests 61 | ansible.builtin.include_tasks: tests.yml 62 | vars: 63 | _share_name: "{{ test_win_share_cluster_name }}" 64 | always: 65 | - name: Cleanup Cluster Test Share 66 | win_share: *cleanup_cluster_share 67 | 68 | - name: Cleanup Cluster Test Folder 69 | ansible.windows.win_file: 70 | path: "{{ test_win_share_cluster_path }}" 71 | state: absent 72 | -------------------------------------------------------------------------------- /tests/integration/targets/win_ping/tasks/main.yml: -------------------------------------------------------------------------------- 1 | # test code for the win_ping module 2 | # (c) 2014, Chris Church 3 | 4 | # This file is part of Ansible 5 | # 6 | # Ansible is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Ansible is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with Ansible. If not, see . 18 | 19 | - name: test win_ping 20 | action: win_ping 21 | register: win_ping_result 22 | 23 | - name: check win_ping result 24 | assert: 25 | that: 26 | - win_ping_result is not failed 27 | - win_ping_result is not changed 28 | - win_ping_result.ping == 'pong' 29 | 30 | - name: test win_ping with data 31 | win_ping: 32 | data: ☠ 33 | register: win_ping_with_data_result 34 | 35 | - name: check win_ping result with data 36 | assert: 37 | that: 38 | - win_ping_with_data_result is not failed 39 | - win_ping_with_data_result is not changed 40 | - win_ping_with_data_result.ping == '☠' 41 | 42 | - name: test win_ping.ps1 with data as complex args 43 | # win_ping.ps1: # TODO: do we want to actually support this? no other tests that I can see... 44 | win_ping: 45 | data: bleep 46 | register: win_ping_ps1_result 47 | 48 | - name: check win_ping.ps1 result with data 49 | assert: 50 | that: 51 | - win_ping_ps1_result is not failed 52 | - win_ping_ps1_result is not changed 53 | - win_ping_ps1_result.ping == 'bleep' 54 | 55 | - name: test win_ping using data=crash so that it throws an exception 56 | win_ping: 57 | data: crash 58 | register: win_ping_crash_result 59 | ignore_errors: yes 60 | 61 | - name: check win_ping_crash result 62 | assert: 63 | that: 64 | - win_ping_crash_result is failed 65 | - win_ping_crash_result is not changed 66 | - 'win_ping_crash_result.msg == "Unhandled exception while executing module: boom"' 67 | -------------------------------------------------------------------------------- /tests/integration/targets/win_reboot/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: make sure win output dir exists 3 | win_file: 4 | path: "{{remote_tmp_dir}}" 5 | state: directory 6 | 7 | - name: reboot with defaults 8 | win_reboot: 9 | 10 | - name: test with negative values for delays 11 | win_reboot: 12 | post_reboot_delay: -0.5 13 | pre_reboot_delay: -61 14 | 15 | - name: schedule a reboot for sometime in the future 16 | win_command: shutdown.exe /r /t 599 17 | 18 | - name: reboot with a shutdown already scheduled 19 | win_reboot: 20 | 21 | # test a reboot that reboots again during the test_command phase 22 | - name: create test file 23 | win_file: 24 | path: '{{remote_tmp_dir}}\win_reboot_test' 25 | state: touch 26 | 27 | - name: reboot with secondary reboot stage 28 | win_reboot: 29 | test_command: '{{ lookup("template", "post_reboot.ps1") }}' 30 | 31 | - name: reboot with test command that fails 32 | win_reboot: 33 | test_command: 'FAIL' 34 | reboot_timeout: 120 35 | register: reboot_fail_test 36 | failed_when: "reboot_fail_test.msg != 'Timed out waiting for post-reboot test command (timeout=120.0)'" 37 | 38 | - name: remove SeRemoteShutdownPrivilege 39 | win_user_right: 40 | name: SeRemoteShutdownPrivilege 41 | users: [] 42 | action: set 43 | register: removed_shutdown_privilege 44 | 45 | - block: 46 | - name: reset connection to ensure privilege change takes effect 47 | meta: reset_connection 48 | 49 | - name: try and reboot without required privilege 50 | win_reboot: 51 | register: fail_privilege 52 | failed_when: 53 | - 'fail_privilege.msg != "win_reboot: Reboot command failed"' 54 | - "'Access is denied.(5)' not in fail_privilege.stderr" 55 | 56 | always: 57 | - name: reset the SeRemoteShutdownPrivilege 58 | win_user_right: 59 | name: SeRemoteShutdownPrivilege 60 | users: '{{ removed_shutdown_privilege.removed }}' 61 | action: add 62 | 63 | - name: reset connection after adding privileges back in 64 | meta: reset_connection 65 | 66 | - name: Use invalid parameter 67 | win_reboot: 68 | foo: bar 69 | ignore_errors: true 70 | register: invalid_parameter 71 | 72 | - name: Ensure task fails with error 73 | assert: 74 | that: 75 | - invalid_parameter is failed 76 | - "invalid_parameter.msg == 'Invalid options for win_reboot: foo'" 77 | -------------------------------------------------------------------------------- /.azure-pipelines/scripts/combine-coverage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | Combine coverage data from multiple jobs, keeping the data only from the most recent attempt from each job. 4 | Coverage artifacts must be named using the format: "Coverage $(System.JobAttempt) {StableUniqueNameForEachJob}" 5 | The recommended coverage artifact name format is: Coverage $(System.JobAttempt) $(System.StageDisplayName) $(System.JobDisplayName) 6 | Keep in mind that Azure Pipelines does not enforce unique job display names (only names). 7 | It is up to pipeline authors to avoid name collisions when deviating from the recommended format. 8 | """ 9 | 10 | from __future__ import annotations 11 | 12 | import os 13 | import re 14 | import shutil 15 | import sys 16 | 17 | 18 | def main(): 19 | """Main program entry point.""" 20 | source_directory = sys.argv[1] 21 | 22 | if '/ansible_collections/' in os.getcwd(): 23 | output_path = "tests/output" 24 | else: 25 | output_path = "test/results" 26 | 27 | destination_directory = os.path.join(output_path, 'coverage') 28 | 29 | if not os.path.exists(destination_directory): 30 | os.makedirs(destination_directory) 31 | 32 | jobs = {} 33 | count = 0 34 | 35 | for name in os.listdir(source_directory): 36 | match = re.search('^Coverage (?P[0-9]+) (?P