From 762fcf78b919ee58d11215c0248a044b947a9360 Mon Sep 17 00:00:00 2001 From: Jordan Borean Date: Fri, 15 Nov 2019 13:53:30 +1000 Subject: [PATCH] win_pester - Align dir scanning with Pester's defaults (#64880) * win_pester - Align dir scanning with Pester's defaults Co-authored-by: Coby Caldwell * Fix sanity issues --- .../fragments/win_pester-path-behaviour.yaml | 2 + .../rst/porting_guides/porting_guide_2.10.rst | 1 + lib/ansible/modules/windows/win_pester.ps1 | 109 ++++++++---------- lib/ansible/modules/windows/win_pester.py | 3 + .../targets/win_pester/files/fail.ps1 | 2 + .../{test01.test.ps1 => test01.tests.ps1} | 0 .../{test02.test.ps1 => test02.tests.ps1} | 0 .../{test03.test.ps1 => test03.tests.ps1} | 0 .../{test04.test.ps1 => test04.tests.ps1} | 0 .../targets/win_pester/tasks/main.yml | 13 ++- .../targets/win_pester/tasks/test.yml | 28 ++--- test/sanity/ignore.txt | 1 - 12 files changed, 82 insertions(+), 77 deletions(-) create mode 100644 changelogs/fragments/win_pester-path-behaviour.yaml create mode 100644 test/integration/targets/win_pester/files/fail.ps1 rename test/integration/targets/win_pester/files/{test01.test.ps1 => test01.tests.ps1} (100%) rename test/integration/targets/win_pester/files/{test02.test.ps1 => test02.tests.ps1} (100%) rename test/integration/targets/win_pester/files/{test03.test.ps1 => test03.tests.ps1} (100%) rename test/integration/targets/win_pester/files/{test04.test.ps1 => test04.tests.ps1} (100%) diff --git a/changelogs/fragments/win_pester-path-behaviour.yaml b/changelogs/fragments/win_pester-path-behaviour.yaml new file mode 100644 index 00000000000..837e0d460aa --- /dev/null +++ b/changelogs/fragments/win_pester-path-behaviour.yaml @@ -0,0 +1,2 @@ +minor_changes: +- win_pester - Only execute ``*.tests.ps1`` in ``path`` to match the default behaviour in Pester - https://github.com/ansible/ansible/issues/55736 diff --git a/docs/docsite/rst/porting_guides/porting_guide_2.10.rst b/docs/docsite/rst/porting_guides/porting_guide_2.10.rst index fc0bc9ec30b..7f8362e3646 100644 --- a/docs/docsite/rst/porting_guides/porting_guide_2.10.rst +++ b/docs/docsite/rst/porting_guides/porting_guide_2.10.rst @@ -81,6 +81,7 @@ Noteworthy module changes * :ref:`vmware_guest_custom_attributes ` module does not require VM name which was a required parameter for releases prior to Ansible 2.10. * :ref:`zabbix_action ` no longer requires ``esc_period`` and ``event_source`` arguments when ``state=absent``. * :ref:`gitlab_user ` no longer requires ``name``, ``email`` and ``password`` arguments when ``state=absent``. +* :ref:`win_pester ` no longer runs all ``*.ps1`` file in the directory specified due to it executing potentially unknown scripts. It will follow the default behaviour of only running tests for files that are like ``*.tests.ps1`` which is built into Pester itself Plugins ======= diff --git a/lib/ansible/modules/windows/win_pester.ps1 b/lib/ansible/modules/windows/win_pester.ps1 index d2dd2745987..f3f2ebdcedc 100644 --- a/lib/ansible/modules/windows/win_pester.ps1 +++ b/lib/ansible/modules/windows/win_pester.ps1 @@ -3,68 +3,68 @@ # Copyright: (c) 2017, Erwan Quelin (@equelin) # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -#Requires -Module Ansible.ModuleUtils.Legacy +#AnsibleRequires -CSharpUtil Ansible.Basic -$ErrorActionPreference = 'Stop' - -$params = Parse-Args -arguments $args -supports_check_mode $true -$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false -$diff_mode = Get-AnsibleParam -obj $params -name "_ansible_diff" -type "bool" -default $false - -# Modules parameters - -$path = Get-AnsibleParam -obj $params -name "path" -type "str" -failifempty $true -$tags = Get-AnsibleParam -obj $params -name "tags" -type "list" -$output_file = Get-AnsibleParam -obj $params -name "output_file" -type "str" -$output_format = Get-AnsibleParam -obj $params -name "output_format" -type "str" -default "NunitXML" -$test_parameters = Get-AnsibleParam -obj $params -name "test_parameters" -type "dict" -$minimum_version = Get-AnsibleParam -obj $params -name "minimum_version" -type "str" -failifempty $false - -$result = @{ - changed = $false +$spec = @{ + options = @{ + output_file = @{ type = "str" } + output_format = @{ type = "str"; default = "NunitXML" } + path = @{ type = "str"; required = $true } + tags = @{ type = "list"; elements = "str" } + test_parameters = @{ type = "dict" } + version = @{ type = "str"; aliases = @(,"minimum_version") } + } + supports_check_mode = $true } -if ($diff_mode) { - $result.diff = @{} -} +$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec) + +$output_file = $module.Params.output_file +$output_format = $module.Params.output_format +$path = $module.Params.path +$tags = $module.Params.tags +$test_parameters = $module.Params.test_parameters +$version = $module.Params.version -# CODE -# Test if parameter $version is valid Try { - $minimum_version = [version]$minimum_version + $version = [version]$version } Catch { - Fail-Json -obj $result -message "Value '$minimum_version' for parameter 'minimum_version' is not a valid version format" + $module.FailJson("Value '$version' for parameter 'minimum_version' is not a valid version format") +} + +# Make sure path is a real path +Try { + $path = $path.TrimEnd("\") + $path = (Get-item -LiteralPath $path).FullName +} +Catch { + $module.FailJson("Cannot find file or directory: '$path' as it does not exist") } # Import Pester module if available -$Module = 'Pester' +$Pester = 'Pester' -If (-not (Get-Module -Name $Module -ErrorAction SilentlyContinue)) { - If (Get-Module -Name $Module -ListAvailable -ErrorAction SilentlyContinue) { - Import-Module $Module +If (-not (Get-Module -Name $Pester -ErrorAction SilentlyContinue)) { + If (Get-Module -Name $Pester -ListAvailable -ErrorAction SilentlyContinue) { + Import-Module $Pester } else { - Fail-Json -obj $result -message "Cannot find module: $Module. Check if pester is installed, and if it is not, install using win_psmodule or win_chocolatey." + $module.FailJson("Cannot find module: $Pester. Check if pester is installed, and if it is not, install using win_psmodule or win_chocolatey.") } } # Add actual pester's module version in the ansible's result variable -$Pester_version = (Get-Module -Name $Module).Version.ToString() -$result.pester_version = $Pester_version +$Pester_version = (Get-Module -Name $Pester).Version.ToString() +$module.Result.pester_version = $Pester_version # Test if the Pester module is available with a version greater or equal than the one specified in the $version parameter -If ((-not (Get-Module -Name $Module -ErrorAction SilentlyContinue | Where-Object {$_.Version -ge $minimum_version})) -and ($minimum_version)) { - Fail-Json -obj $result -message "$Module version is not greater or equal to $minimum_version" -} - -# Testing if test file or directory exist -If (-not (Test-Path -LiteralPath $path)) { - Fail-Json -obj $result -message "Cannot find file or directory: '$path' as it does not exist" +If ((-not (Get-Module -Name $Pester -ErrorAction SilentlyContinue | Where-Object {$_.Version -ge $version})) -and ($version)) { + $module.FailJson("$Pester version is not greater or equal to $version") } #Prepare Invoke-Pester parameters depending of the Pester's version. #Invoke-Pester output deactivation behave differently depending on the Pester's version -If ($result.pester_version -ge "4.0.0") { +If ($module.Result.pester_version -ge "4.0.0") { $Parameters = @{ "show" = "none" "PassThru" = $True @@ -84,6 +84,7 @@ if($output_file){ $Parameters.OutputFile = $output_file $Parameters.OutputFormat = $output_format } + # Run Pester tests If (Test-Path -LiteralPath $path -PathType Leaf) { $test_parameters_check_mode_msg = '' @@ -94,30 +95,22 @@ If (Test-Path -LiteralPath $path -PathType Leaf) { else { $Parameters.Script = $Path } - if ($check_mode) { - $result.output = "Run pester test in the file: $path$test_parameters_check_mode_msg" + + if ($module.CheckMode) { + $module.Result.output = "Run pester test in the file: $path$test_parameters_check_mode_msg" } else { - try { - $result.output = Invoke-Pester @Parameters - } catch { - Fail-Json -obj $result -message $_.Exception - } + $module.Result.output = Invoke-Pester @Parameters } } else { - # Run Pester tests against all the .ps1 file in the local folder - $files = Get-ChildItem -Path $path | Where-Object {$_.extension -eq ".ps1"} + $Parameters.Script = $path - if ($check_mode) { - $result.output = "Run pester test(s) who are in the folder: $path" + if ($module.CheckMode) { + $module.Result.output = "Run Pester test(s): $path" } else { - try { - $result.output = Invoke-Pester $files.FullName @Parameters - } catch { - Fail-Json -obj $result -message $_.Exception - } + $module.Result.output = Invoke-Pester @Parameters } } -$result.changed = $true +$module.Result.changed = $true -Exit-Json -obj $result +$module.ExitJson() diff --git a/lib/ansible/modules/windows/win_pester.py b/lib/ansible/modules/windows/win_pester.py index bfbc3d0d6f8..c17009fb708 100644 --- a/lib/ansible/modules/windows/win_pester.py +++ b/lib/ansible/modules/windows/win_pester.py @@ -52,6 +52,9 @@ options: version: description: - Minimum version of the pester module that has to be available on the remote host. + type: str + aliases: + - minimum_version author: - Erwan Quelin (@equelin) - Prasoon Karunan V (@prasoonkarunan) diff --git a/test/integration/targets/win_pester/files/fail.ps1 b/test/integration/targets/win_pester/files/fail.ps1 new file mode 100644 index 00000000000..4bd20a601c3 --- /dev/null +++ b/test/integration/targets/win_pester/files/fail.ps1 @@ -0,0 +1,2 @@ +# This makes sure that a file that does not end with *.test.ps1 does not run +throw "should never fail" diff --git a/test/integration/targets/win_pester/files/test01.test.ps1 b/test/integration/targets/win_pester/files/test01.tests.ps1 similarity index 100% rename from test/integration/targets/win_pester/files/test01.test.ps1 rename to test/integration/targets/win_pester/files/test01.tests.ps1 diff --git a/test/integration/targets/win_pester/files/test02.test.ps1 b/test/integration/targets/win_pester/files/test02.tests.ps1 similarity index 100% rename from test/integration/targets/win_pester/files/test02.test.ps1 rename to test/integration/targets/win_pester/files/test02.tests.ps1 diff --git a/test/integration/targets/win_pester/files/test03.test.ps1 b/test/integration/targets/win_pester/files/test03.tests.ps1 similarity index 100% rename from test/integration/targets/win_pester/files/test03.test.ps1 rename to test/integration/targets/win_pester/files/test03.tests.ps1 diff --git a/test/integration/targets/win_pester/files/test04.test.ps1 b/test/integration/targets/win_pester/files/test04.tests.ps1 similarity index 100% rename from test/integration/targets/win_pester/files/test04.test.ps1 rename to test/integration/targets/win_pester/files/test04.tests.ps1 diff --git a/test/integration/targets/win_pester/tasks/main.yml b/test/integration/targets/win_pester/tasks/main.yml index 8c7b4791f1e..ca04a1fe5a2 100644 --- a/test/integration/targets/win_pester/tasks/main.yml +++ b/test/integration/targets/win_pester/tasks/main.yml @@ -1,8 +1,11 @@ --- -- name: create test folder +- name: create test folder(s) win_file: - path: '{{test_win_pester_path}}\Modules' + path: '{{test_win_pester_path}}\{{item}}' state: directory + with_items: + - Modules + - Tests - name: download Pester module from S3 bucket win_get_url: @@ -30,11 +33,13 @@ - name: copy test files win_copy: src: files/ - dest: '{{test_win_pester_path}}\' + dest: '{{test_win_pester_path}}\Tests' - block: - name: run Pester tests include_tasks: test.yml + vars: + test_path: '{{ test_win_pester_path }}\Tests' always: - name: remove custom pester location on the PSModulePath @@ -44,7 +49,7 @@ state: absent elements: - '{{test_win_pester_path}}\Modules' - + - name: delete test folder win_file: path: '{{test_win_pester_path}}' diff --git a/test/integration/targets/win_pester/tasks/test.yml b/test/integration/targets/win_pester/tasks/test.yml index 2baf383438c..6268633b27e 100644 --- a/test/integration/targets/win_pester/tasks/test.yml +++ b/test/integration/targets/win_pester/tasks/test.yml @@ -1,26 +1,26 @@ --- - name: Run Pester test(s) specifying a fake test file win_pester: - path: '{{test_win_pester_path}}\fakefile.ps1' + path: '{{test_path}}\fakefile.ps1' register: fake_file - failed_when: '"Cannot find file or directory: ''" + test_win_pester_path + "\\fakefile.ps1'' as it does not exist" not in fake_file.msg' + failed_when: '"Cannot find file or directory: ''" + test_path + "\\fakefile.ps1'' as it does not exist" not in fake_file.msg' - name: Run Pester test(s) specifying a fake folder win_pester: - path: '{{test_win_pester_path }}\fakedir' + path: '{{test_path }}\fakedir' register: fake_folder - failed_when: '"Cannot find file or directory: ''" + test_win_pester_path + "\\fakedir'' as it does not exist" not in fake_folder.msg' + failed_when: '"Cannot find file or directory: ''" + test_path + "\\fakedir'' as it does not exist" not in fake_folder.msg' - name: Run Pester test(s) specifying a test file and a higher pester version win_pester: - path: '{{test_win_pester_path}}\test01.test.ps1' + path: '{{test_path}}\test01.tests.ps1' minimum_version: '6.0.0' register: invalid_version failed_when: '"Pester version is not greater or equal to 6.0.0" not in invalid_version.msg' - name: Run Pester test(s) specifying a test file win_pester: - path: '{{test_win_pester_path}}\test01.test.ps1' + path: '{{test_path}}\test01.tests.ps1' register: file_result - name: assert Run Pester test(s) specify a test file @@ -32,7 +32,7 @@ - name: Run Pester test(s) specifying a test file and with a minimum mandatory Pester version win_pester: - path: '{{test_win_pester_path}}\test01.test.ps1' + path: '{{test_path}}\test01.tests.ps1' minimum_version: 3.0.0 register: file_result_with_version @@ -45,7 +45,7 @@ - name: Run Pester test(s) located in a folder. Folder path end with '\' win_pester: - path: '{{test_win_pester_path}}\' + path: '{{test_path}}\' register: dir_with_ending_slash - name: assert Run Pester test(s) located in a folder. Folder path end with '\' @@ -57,7 +57,7 @@ - name: Run Pester test(s) located in a folder. Folder path does not end with '\' win_pester: - path: '{{test_win_pester_path}}' + path: '{{test_path}}' register: dir_without_ending_slash - name: assert Run Pester test(s) located in a folder. Folder does not end with '\' @@ -69,7 +69,7 @@ - name: Run Pester test(s) located in a folder and with a minimum mandatory Pester version win_pester: - path: '{{test_win_pester_path}}' + path: '{{test_path}}' minimum_version: 3.0.0 register: dir_with_version @@ -82,7 +82,7 @@ - name: Run Pester test(s) specifying a test file without specifying tag win_pester: - path: '{{test_win_pester_path}}\test03.test.ps1' + path: '{{test_path}}\test03.tests.ps1' register: test_no_tag - name: assert Run Pester test(s) specifying a test file and all tests executed @@ -93,7 +93,7 @@ - name: Run Pester test(s) specifying a test file with tag win_pester: - path: '{{test_win_pester_path}}\test03.test.ps1' + path: '{{test_path}}\test03.tests.ps1' tags: tag1 register: test_with_tag @@ -105,7 +105,7 @@ - name: Run Pester test(s) specifying a test file with parameters win_pester: - path: '{{test_win_pester_path}}\test04.test.ps1' + path: '{{test_path}}\test04.tests.ps1' test_parameters: Process: lsass Service: bits @@ -120,7 +120,7 @@ - name: Run Pester test(s) specifying a test file by generating test result xml win_pester: - path: '{{test_win_pester_path}}\test03.test.ps1' + path: '{{test_path}}\test03.tests.ps1' output_file: '{{test_report_file}}' - name: Checks if the output result file exists diff --git a/test/sanity/ignore.txt b/test/sanity/ignore.txt index 18736520550..6c1488d819d 100644 --- a/test/sanity/ignore.txt +++ b/test/sanity/ignore.txt @@ -5022,7 +5022,6 @@ lib/ansible/modules/windows/win_package.ps1 pslint:PSUseApprovedVerbs lib/ansible/modules/windows/win_pagefile.ps1 pslint:PSCustomUseLiteralPath lib/ansible/modules/windows/win_pagefile.ps1 pslint:PSUseDeclaredVarsMoreThanAssignments # New PR - bug test_path should be testPath lib/ansible/modules/windows/win_pagefile.ps1 pslint:PSUseSupportsShouldProcess -lib/ansible/modules/windows/win_pester.ps1 pslint:PSCustomUseLiteralPath lib/ansible/modules/windows/win_product_facts.ps1 pslint:PSCustomUseLiteralPath lib/ansible/modules/windows/win_psexec.ps1 validate-modules:parameter-type-not-in-doc lib/ansible/modules/windows/win_rabbitmq_plugin.ps1 pslint:PSAvoidUsingInvokeExpression