|
|
---
|
|
|
- name: sample config for traceback behavior
|
|
|
set_fact:
|
|
|
traceback_on_error: |
|
|
|
{{ lookup('ansible._protomatter.config', 'DISPLAY_TRACEBACK') is contains 'error' }}
|
|
|
|
|
|
- name: fetch host information
|
|
|
get_info:
|
|
|
register: test_host_info
|
|
|
|
|
|
- name: test normal module execution
|
|
|
test_fail:
|
|
|
register: normal
|
|
|
|
|
|
- name: assert test normal module execution
|
|
|
assert:
|
|
|
that:
|
|
|
- not normal is failed
|
|
|
|
|
|
- name: test exec_wrapper with async
|
|
|
test_fail:
|
|
|
async: 60
|
|
|
poll: 5
|
|
|
|
|
|
- name: test out Windows specific exec wrapper tests
|
|
|
include_tasks: windows.yml
|
|
|
when: test_host_info.is_windows
|
|
|
|
|
|
- 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"
|
|
|
- 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"'
|
|
|
- not traceback_on_error or "throw [ArgumentException]\"module is thrown\"" in throw_module.exception
|
|
|
- not traceback_on_error or throw_module.exception is search "at <ScriptBlock>, ansible.legacy.test_fail.ps1. line 47"
|
|
|
|
|
|
- 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 pseudo 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"'
|
|
|
- not traceback_on_error or "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."'
|
|
|
- not traceback_on_error or "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 is contains("Unhandled exception while executing module: Exception calling \"GetFullPath\" with \"1\" argument(s): ")'
|
|
|
- not traceback_on_error or "[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"'
|
|
|
- 'not traceback_on_error or "throw \"exception in function\"" in function_exception.exception'
|
|
|
- 'not traceback_on_error or "at Test-ThrowException, ansible.legacy.test_fail.ps1: 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"
|
|
|
- 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 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: define common environment variables for all tasks
|
|
|
set_fact:
|
|
|
common_env_ars:
|
|
|
String: string value
|
|
|
Int: 1234
|
|
|
Bool: True
|
|
|
double_quote: 'double " quote'
|
|
|
single_quote: "single ' quote"
|
|
|
|
|
|
- name: define Windows specific environment variables
|
|
|
set_fact:
|
|
|
windows_env_ars:
|
|
|
hyphen-var: abc@123
|
|
|
'_-(){}[]<>*+-/\?"''!@#$%^&|;:i,.`~0': '_-(){}[]<>*+-/\?"''!@#$%^&|;:i,.`~0'
|
|
|
'‘key': 'value‚'
|
|
|
|
|
|
# These env vars don't work with the shell inline commands so we only test
|
|
|
# them with Windows.
|
|
|
- name: test out environment block for task
|
|
|
get_env:
|
|
|
environment: '{{ common_env_ars | combine(windows_env_ars if test_host_info.is_windows else {}) }}'
|
|
|
register: environment_block
|
|
|
|
|
|
- name: test out environment block for task with async
|
|
|
get_env:
|
|
|
environment: '{{ common_env_ars | combine(windows_env_ars if test_host_info.is_windows else {}) }}'
|
|
|
register: environment_block_async
|
|
|
async: 60
|
|
|
poll: 5
|
|
|
|
|
|
- name: assert environment block for task
|
|
|
assert:
|
|
|
that:
|
|
|
- '"String=string value" in environment_block.env_vars'
|
|
|
- '"String=string value" in environment_block_async.env_vars'
|
|
|
- '"Int=1234" in environment_block.env_vars'
|
|
|
- '"Int=1234" in environment_block_async.env_vars'
|
|
|
- '"Bool=True" in environment_block.env_vars'
|
|
|
- '"Bool=True" in environment_block_async.env_vars'
|
|
|
- '"double_quote=double \" quote" in environment_block.env_vars'
|
|
|
- '"double_quote=double \" quote" in environment_block_async.env_vars'
|
|
|
- '"single_quote=single '' quote" in environment_block.env_vars'
|
|
|
- '"single_quote=single '' quote" in environment_block_async.env_vars'
|
|
|
|
|
|
- name: assert environment block for task on Windows
|
|
|
assert:
|
|
|
that:
|
|
|
- '"hyphen-var=abc@123" in environment_block.env_vars'
|
|
|
- '"hyphen-var=abc@123" in environment_block_async.env_vars'
|
|
|
# yaml escaping rules - (\\ == \), (\" == "), ('' == ')
|
|
|
- '"_-(){}[]<>*+-/\\?\"''!@#$%^&|;:i,.`~0=_-(){}[]<>*+-/\\?\"''!@#$%^&|;:i,.`~0" in environment_block.env_vars'
|
|
|
- '"_-(){}[]<>*+-/\\?\"''!@#$%^&|;:i,.`~0=_-(){}[]<>*+-/\\?\"''!@#$%^&|;:i,.`~0" in environment_block_async.env_vars'
|
|
|
- '"‘key=value‚" in environment_block.env_vars'
|
|
|
- '"‘key=value‚" in environment_block_async.env_vars'
|
|
|
when: test_host_info.is_windows
|
|
|
|
|
|
- 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
|
|
|
|
|
|
- name: test module cannot access exec wrapper scope
|
|
|
test_exec_wrapper_scope:
|
|
|
register: exec_wrapper_scope
|
|
|
|
|
|
- name: assert test module cannot access exec wrapper scope
|
|
|
assert:
|
|
|
that:
|
|
|
- exec_wrapper_scope.module_using_namespace == 'System.Management.Automation.Language.Parser'
|
|
|
- exec_wrapper_scope.missing_using_namespace == True
|
|
|
- exec_wrapper_scope.script_var == 'foo'
|
|
|
- exec_wrapper_scope.util_res.module_using_namespace == 'System.Security.Cryptography.X509Certificates.X509Certificate2'
|
|
|
- exec_wrapper_scope.util_res.missing_using_namespace == True
|
|
|
- exec_wrapper_scope.util_res.script_var == 'bar'
|
|
|
|
|
|
- name: test module without any util references
|
|
|
test_no_utils:
|
|
|
foo: bar
|
|
|
register: no_utils_res
|
|
|
|
|
|
- name: assert test module without any util references
|
|
|
assert:
|
|
|
that:
|
|
|
- no_utils_res is not changed
|
|
|
- no_utils_res.complex_args['foo'] == 'bar'
|
|
|
|
|
|
- name: test module with invalid syntax
|
|
|
test_invalid_syntax:
|
|
|
register: invalid_syntax
|
|
|
ignore_errors: true
|
|
|
|
|
|
- name: assert test module with invalid syntax
|
|
|
assert:
|
|
|
that:
|
|
|
- invalid_syntax is failed
|
|
|
- invalid_syntax.msg is contains("Failed to parse script 'ansible.legacy.test_invalid_syntax.ps1'")
|
|
|
|
|
|
- name: test module with invalid module_util syntax
|
|
|
test_invalid_util_syntax:
|
|
|
register: invalid_util_syntax
|
|
|
ignore_errors: true
|
|
|
|
|
|
- name: assert test module with invalid module_util syntax
|
|
|
assert:
|
|
|
that:
|
|
|
- invalid_util_syntax is failed
|
|
|
- invalid_util_syntax.msg is contains("Failed to parse script 'Ansible.ModuleUtils.InvalidSyntax.psm1'")
|
|
|
|
|
|
- name: check if pipelining is supported on connection
|
|
|
set_fact:
|
|
|
connection_pipelining: |
|
|
|
{{ lookup('config', 'pipelining', plugin_type='connection', plugin_name=ansible_connection, on_missing='skip') }}
|
|
|
|
|
|
# Needs to be define outside the block, will emit a warning
|
|
|
# if the block gets skipped as the name for each task fails templating
|
|
|
- name: determine if next tests are with or without pipelining
|
|
|
set_fact:
|
|
|
operation: '{{ connection_pipelining | ternary("without", "with") }}'
|
|
|
|
|
|
- when: connection_pipelining != [] # on_missing='skip' results in []
|
|
|
block:
|
|
|
- name: run pwsh module {{ operation }} pipelining
|
|
|
test_fail:
|
|
|
vars:
|
|
|
ansible_pipelining: '{{ not connection_pipelining }}'
|
|
|
|
|
|
- name: run async pwsh module {{ operation }} pipelining
|
|
|
test_fail:
|
|
|
async: 60
|
|
|
poll: 5
|
|
|
vars:
|
|
|
ansible_pipelining: '{{ not connection_pipelining }}'
|