|
|
---
|
|
|
- name: fetch current target date/time for log filtering
|
|
|
raw: '[datetime]::now | Out-String'
|
|
|
register: test_starttime
|
|
|
|
|
|
- name: test normal module execution
|
|
|
test_fail:
|
|
|
register: normal
|
|
|
|
|
|
- name: assert test normal module execution
|
|
|
assert:
|
|
|
that:
|
|
|
- not normal is failed
|
|
|
|
|
|
- name: test fail module execution
|
|
|
test_fail:
|
|
|
data: fail
|
|
|
register: fail_module
|
|
|
ignore_errors: yes
|
|
|
|
|
|
- name: assert test fail module execution
|
|
|
assert:
|
|
|
that:
|
|
|
- fail_module is failed
|
|
|
- fail_module.msg == "fail message"
|
|
|
- not fail_module.exception is defined
|
|
|
|
|
|
- name: test module with exception thrown
|
|
|
test_fail:
|
|
|
data: throw
|
|
|
register: throw_module
|
|
|
ignore_errors: yes
|
|
|
|
|
|
- name: assert test module with exception thrown
|
|
|
assert:
|
|
|
that:
|
|
|
- throw_module is failed
|
|
|
- 'throw_module.msg == "Unhandled exception while executing module: module is thrown"'
|
|
|
- '"throw [ArgumentException]\"module is thrown\"" in throw_module.exception'
|
|
|
|
|
|
- name: test module with error msg
|
|
|
test_fail:
|
|
|
data: error
|
|
|
register: error_module
|
|
|
ignore_errors: yes
|
|
|
vars:
|
|
|
# Running with coverage means the module is run from a script and not as a psuedo script in a pipeline. This
|
|
|
# results in a different error message being returned so we disable coverage collection for this task.
|
|
|
_ansible_coverage_remote_output: ''
|
|
|
|
|
|
- name: assert test module with error msg
|
|
|
assert:
|
|
|
that:
|
|
|
- error_module is failed
|
|
|
- 'error_module.msg == "Unhandled exception while executing module: error"'
|
|
|
- '"Write-Error -Message $data" in error_module.exception'
|
|
|
|
|
|
- name: test module with cmdlet error
|
|
|
test_fail:
|
|
|
data: cmdlet_error
|
|
|
register: cmdlet_error
|
|
|
ignore_errors: yes
|
|
|
|
|
|
- name: assert test module with cmdlet error
|
|
|
assert:
|
|
|
that:
|
|
|
- cmdlet_error is failed
|
|
|
- 'cmdlet_error.msg == "Unhandled exception while executing module: Cannot find drive. A drive with the name ''fake'' does not exist."'
|
|
|
- '"Get-Item -Path \"fake:\\path\"" in cmdlet_error.exception'
|
|
|
|
|
|
- name: test module with .NET exception
|
|
|
test_fail:
|
|
|
data: dotnet_exception
|
|
|
register: dotnet_exception
|
|
|
ignore_errors: yes
|
|
|
|
|
|
- name: assert test module with .NET exception
|
|
|
assert:
|
|
|
that:
|
|
|
- dotnet_exception is failed
|
|
|
- 'dotnet_exception.msg == "Unhandled exception while executing module: Exception calling \"GetFullPath\" with \"1\" argument(s): \"The path is not of a legal form.\""'
|
|
|
- '"[System.IO.Path]::GetFullPath($null)" in dotnet_exception.exception'
|
|
|
|
|
|
- name: test module with function exception
|
|
|
test_fail:
|
|
|
data: function_throw
|
|
|
register: function_exception
|
|
|
ignore_errors: yes
|
|
|
vars:
|
|
|
_ansible_coverage_remote_output: ''
|
|
|
|
|
|
- name: assert test module with function exception
|
|
|
assert:
|
|
|
that:
|
|
|
- function_exception is failed
|
|
|
- 'function_exception.msg == "Unhandled exception while executing module: exception in function"'
|
|
|
- '"throw \"exception in function\"" in function_exception.exception'
|
|
|
- '"at Test-ThrowException, <No file>: line" in function_exception.exception'
|
|
|
|
|
|
- name: test module with fail process but Exit-Json
|
|
|
test_fail:
|
|
|
data: proc_exit_fine
|
|
|
register: proc_exit_fine
|
|
|
|
|
|
- name: assert test module with fail process but Exit-Json
|
|
|
assert:
|
|
|
that:
|
|
|
- not proc_exit_fine is failed
|
|
|
|
|
|
- name: test module with fail process but Fail-Json
|
|
|
test_fail:
|
|
|
data: proc_exit_fail
|
|
|
register: proc_exit_fail
|
|
|
ignore_errors: yes
|
|
|
|
|
|
- name: assert test module with fail process but Fail-Json
|
|
|
assert:
|
|
|
that:
|
|
|
- proc_exit_fail is failed
|
|
|
- proc_exit_fail.msg == "proc_exit_fail"
|
|
|
- not proc_exit_fail.exception is defined
|
|
|
|
|
|
- name: test out invalid options
|
|
|
test_invalid_requires:
|
|
|
register: invalid_options
|
|
|
|
|
|
- name: assert test out invalid options
|
|
|
assert:
|
|
|
that:
|
|
|
- invalid_options is successful
|
|
|
- invalid_options.output == "output"
|
|
|
|
|
|
- name: test out invalid os version
|
|
|
test_min_os_version:
|
|
|
register: invalid_os_version
|
|
|
ignore_errors: yes
|
|
|
|
|
|
- name: assert test out invalid os version
|
|
|
assert:
|
|
|
that:
|
|
|
- invalid_os_version is failed
|
|
|
- '"This module cannot run on this OS as it requires a minimum version of 20.0, actual was " in invalid_os_version.msg'
|
|
|
|
|
|
- name: test out invalid powershell version
|
|
|
test_min_ps_version:
|
|
|
register: invalid_ps_version
|
|
|
ignore_errors: yes
|
|
|
|
|
|
- name: assert test out invalid powershell version
|
|
|
assert:
|
|
|
that:
|
|
|
- invalid_ps_version is failed
|
|
|
- '"This module cannot run as it requires a minimum PowerShell version of 20.0.0.0, actual was " in invalid_ps_version.msg'
|
|
|
|
|
|
- name: test out environment block for task
|
|
|
win_shell: set
|
|
|
args:
|
|
|
executable: cmd.exe
|
|
|
environment:
|
|
|
String: string value
|
|
|
Int: 1234
|
|
|
Bool: True
|
|
|
double_quote: 'double " quote'
|
|
|
single_quote: "single ' quote"
|
|
|
hyphen-var: abc@123
|
|
|
'_-(){}[]<>*+-/\?"''!@#$%^&|;:i,.`~0': '_-(){}[]<>*+-/\?"''!@#$%^&|;:i,.`~0'
|
|
|
'‘key': 'value‚'
|
|
|
register: environment_block
|
|
|
|
|
|
- name: assert environment block for task
|
|
|
assert:
|
|
|
that:
|
|
|
- '"String=string value" in environment_block.stdout_lines'
|
|
|
- '"Int=1234" in environment_block.stdout_lines'
|
|
|
- '"Bool=True" in environment_block.stdout_lines'
|
|
|
- '"double_quote=double \" quote" in environment_block.stdout_lines'
|
|
|
- '"single_quote=single '' quote" in environment_block.stdout_lines'
|
|
|
- '"hyphen-var=abc@123" in environment_block.stdout_lines'
|
|
|
# yaml escaping rules - (\\ == \), (\" == "), ('' == ')
|
|
|
- '"_-(){}[]<>*+-/\\?\"''!@#$%^&|;:i,.`~0=_-(){}[]<>*+-/\\?\"''!@#$%^&|;:i,.`~0" in environment_block.stdout_lines'
|
|
|
- '"‘key=value‚" in environment_block.stdout_lines'
|
|
|
|
|
|
- name: test out become requires without become_user set
|
|
|
test_all_options:
|
|
|
register: become_system
|
|
|
|
|
|
- name: assert become requires without become_user set
|
|
|
assert:
|
|
|
that:
|
|
|
- become_system is successful
|
|
|
- become_system.output == "S-1-5-18"
|
|
|
|
|
|
- set_fact:
|
|
|
become_test_username: ansible_become_test
|
|
|
gen_pw: "{{ 'password123!' + lookup('password', '/dev/null chars=ascii_letters,digits length=8') }}"
|
|
|
|
|
|
- name: execute tests and ensure that test user is deleted regardless of success/failure
|
|
|
block:
|
|
|
- name: create unprivileged user
|
|
|
win_user:
|
|
|
name: "{{ become_test_username }}"
|
|
|
password: "{{ gen_pw }}"
|
|
|
update_password: always
|
|
|
groups: Users
|
|
|
register: become_test_user_result
|
|
|
|
|
|
- name: create tempdir for test user
|
|
|
win_file:
|
|
|
path: C:\Windows\TEMP\test-dir
|
|
|
state: directory
|
|
|
|
|
|
- name: deny delete permissions on new temp dir for test user
|
|
|
win_acl:
|
|
|
path: C:\Windows\TEMP\test-dir
|
|
|
user: '{{ become_test_user_result.sid }}'
|
|
|
type: '{{ item.type }}'
|
|
|
rights: '{{ item.rights }}'
|
|
|
loop:
|
|
|
- type: allow
|
|
|
rights: ListDirectory, CreateFiles, CreateDirectories, ReadAttributes, ReadExtendedAttributes, WriteData, WriteAttributes, WriteExtendedAttributes, Synchronize
|
|
|
- type: deny
|
|
|
rights: DeleteSubdirectoriesAndFiles, Delete
|
|
|
|
|
|
- name: ensure current user is not the become user
|
|
|
win_shell: whoami
|
|
|
register: whoami_out
|
|
|
|
|
|
- name: verify output
|
|
|
assert:
|
|
|
that:
|
|
|
- not whoami_out.stdout_lines[0].endswith(become_test_username)
|
|
|
|
|
|
- name: get become user profile dir so we can clean it up later
|
|
|
vars: &become_vars
|
|
|
ansible_become_user: "{{ become_test_username }}"
|
|
|
ansible_become_password: "{{ gen_pw }}"
|
|
|
ansible_become_method: runas
|
|
|
ansible_become: yes
|
|
|
win_shell: $env:USERPROFILE
|
|
|
register: profile_dir_out
|
|
|
|
|
|
- name: ensure profile dir contains test username (eg, if become fails silently, prevent deletion of real user profile)
|
|
|
assert:
|
|
|
that:
|
|
|
- become_test_username in profile_dir_out.stdout_lines[0]
|
|
|
|
|
|
- name: test out become requires when become_user set
|
|
|
test_all_options:
|
|
|
vars: *become_vars
|
|
|
register: become_system
|
|
|
|
|
|
- name: assert become requires when become_user set
|
|
|
assert:
|
|
|
that:
|
|
|
- become_system is successful
|
|
|
- become_system.output == become_test_user_result.sid
|
|
|
|
|
|
- name: run module with tempdir with no delete access
|
|
|
win_ping:
|
|
|
register: temp_deletion_warning
|
|
|
vars:
|
|
|
<<: *become_vars
|
|
|
ansible_remote_tmp: C:\Windows\TEMP\test-dir
|
|
|
|
|
|
- name: assert warning about tmpdir deletion is present
|
|
|
assert:
|
|
|
that:
|
|
|
- temp_deletion_warning.warnings | count == 1
|
|
|
- >-
|
|
|
temp_deletion_warning.warnings[0] is
|
|
|
regex("(?i).*Failed to cleanup temporary directory 'C:\\\\Windows\\\\TEMP\\\\test-dir\\\\.*' used for compiling C# code\\. Files may still be present after the task is complete\\..*")
|
|
|
|
|
|
always:
|
|
|
- name: ensure test user is deleted
|
|
|
win_user:
|
|
|
name: "{{ become_test_username }}"
|
|
|
state: absent
|
|
|
|
|
|
- name: ensure test user profile is deleted
|
|
|
# NB: have to work around powershell limitation of long filenames until win_file fixes it
|
|
|
win_shell: rmdir /S /Q {{ profile_dir_out.stdout_lines[0] }}
|
|
|
args:
|
|
|
executable: cmd.exe
|
|
|
when: become_test_username in profile_dir_out.stdout_lines[0] | default("")
|
|
|
|
|
|
- name: remove test tempdir
|
|
|
win_file:
|
|
|
path: C:\Windows\TEMP\test-dir
|
|
|
state: absent
|
|
|
|
|
|
- name: test common functions in exec
|
|
|
test_common_functions:
|
|
|
register: common_functions_res
|
|
|
|
|
|
- name: assert test common functions in exec
|
|
|
assert:
|
|
|
that:
|
|
|
- not common_functions_res is failed
|
|
|
- common_functions_res.msg == "good"
|
|
|
|
|
|
- name: get PS events containing module args or envvars created since test start
|
|
|
raw: |
|
|
|
$dt=[datetime]"{{ test_starttime.stdout|trim }}"
|
|
|
(Get-WinEvent -LogName Microsoft-Windows-Powershell/Operational |
|
|
|
? { $_.TimeCreated -ge $dt -and $_.Message -match "fail_module|hyphen-var" }).Count
|
|
|
register: ps_log_count
|
|
|
|
|
|
- name: assert no PS events contain module args or envvars
|
|
|
assert:
|
|
|
that:
|
|
|
- ps_log_count.stdout | int == 0
|
|
|
|
|
|
- name: test module that sets HadErrors with no error records
|
|
|
test_rc_1:
|
|
|
register: module_had_errors
|
|
|
|
|
|
- name: assert test module that sets HadErrors with no error records
|
|
|
assert:
|
|
|
that:
|
|
|
- module_had_errors.rc == 0
|