├── .github ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── DeploymentReadinessChecker.psd1 ├── DeploymentReadinessChecker.psm1 ├── LICENSE ├── README.md ├── ReadinessValidationScript └── Example.Tests.ps1 ├── ReportUnit ├── LICENSE └── ReportUnit.exe ├── Tests └── Unit │ └── DeploymentReadinessChecker.Tests.ps1 ├── appveyor.yml ├── docs └── index.md └── mkdocs.yml /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to contribute 2 | Contributions to DeploymentReadinessChecker are highly encouraged and desired. Below are some guidelines that will help make the process as smooth as possible. 3 | 4 | # Getting Started 5 | * Make sure you have a [GitHub account](https://github.com/signup/free) 6 | * Submit a new issue, assuming one does not already exist. 7 | * Clearly describe the issue including steps to reproduce when it is a bug. 8 | * Make sure you fill in the earliest version that you know has the issue. 9 | * Fork the repository on GitHub 10 | 11 | # Suggesting Enhancements 12 | I want to know what you think is missing from DeploymentReadinessChecker and how it can be made better. 13 | * When submitting an issue for an enhancement, please be as clear as possible about why you think the enhancement is needed and what the benefit of 14 | it would be. 15 | 16 | # Making Changes 17 | * From your fork of the repository, create a topic/feature branch where work on your change will take place. 18 | * To quickly create a topic/feature branch based on master; `git checkout -b my_topic_branch master`. Please avoid working directly on the `master` branch. 19 | * Make commits of logical units. 20 | * Check for unnecessary whitespace with `git diff --check` before committing. 21 | * Please follow the prevailing code conventions in the repository. Differences in style make the code harder to understand for everyone. 22 | * Make sure your commit messages are in the proper format. 23 | ```` 24 | Add more cowbell to Get-Something.ps1 25 | 26 | The functionaly of Get-Something would be greatly improved if there was a little 27 | more 'pizzazz' added to it. I propose a cowbell. Adding more cowbell has been 28 | shown in studies to both increase one's mojo, and cement one's status 29 | as a rock legend. 30 | ```` 31 | 32 | * Make sure you have added all the necessary Pester tests for your changes. 33 | * Run the Pester tests in the module and make sure they _all_ pass, to verify that your changes have not broken anything. 34 | 35 | # Documentation 36 | I am infallible and as such my documenation needs no corectoin. In the highly 37 | unlikely event that it is _not_ the case, contributions to update or add documentation 38 | are highly appreciated. 39 | 40 | # Submitting Changes 41 | * Push your changes to a topic/feature branch in your fork of the repository. 42 | * Submit a pull request to the main repository. 43 | * Once the pull request has been reviewed and accepted, it will be merged with the master branch in the main repository. 44 | * Be proud of your awesomeness and celebrate. 45 | 46 | # Additional Resources 47 | * [General GitHub documentation](https://help.github.com/) 48 | * [GitHub forking documentation](https://guides.github.com/activities/forking/) 49 | * [GitHub pull request documentation](https://help.github.com/send-pull-requests/) 50 | * [GitHub Flow guide](https://guides.github.com/introduction/flow/) 51 | * [GitHub's guide to contributing to open source projects](https://guides.github.com/activities/contributing-to-open-source/) -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Expected Behavior 4 | 5 | 6 | 7 | ## Current Behavior 8 | 9 | 10 | 11 | ## Possible Solution 12 | 13 | 14 | 15 | ## Steps to Reproduce (for bugs) 16 | 17 | 18 | 1. 19 | 2. 20 | 3. 21 | 4. 22 | 23 | ## Context 24 | 25 | 26 | 27 | ## Your Environment 28 | 29 | * Module version used: 30 | * Operating System and PowerShell version: -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Description 4 | 5 | 6 | ## Related Issue 7 | 8 | 9 | 10 | 11 | 12 | ## Motivation and Context 13 | 14 | 15 | ## How Has This Been Tested? 16 | 17 | 18 | 19 | 20 | ## Screenshots (if appropriate): 21 | 22 | ## Types of changes 23 | 24 | - [ ] Bug fix (non-breaking change which fixes an issue) 25 | - [ ] New feature (non-breaking change which adds functionality) 26 | - [ ] Breaking change (fix or feature that would cause existing functionality to change) 27 | 28 | ## Checklist: 29 | 30 | 31 | - [ ] My code follows the code style of this project. 32 | - [ ] My change requires a change to the documentation. 33 | - [ ] I have updated the documentation accordingly. 34 | - [ ] I have read the **CONTRIBUTING** document. 35 | - [ ] I have added tests to cover my changes. 36 | - [ ] All new and existing tests passed. -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.sln.docstates 8 | # Build results 9 | [Dd]ebug/ 10 | [Dd]ebugPublic/ 11 | [Rr]elease/ 12 | 13 | # Visual Studio 2015 cache/options directory 14 | .vs/ 15 | 16 | #NUNIT 17 | *.VisualState.xml 18 | TestResult.xml 19 | 20 | # Visual Studio profiler 21 | *.psess 22 | *.vsp 23 | *.vspx 24 | # TFS 2012 Local Workspace 25 | $tf/ 26 | 27 | # ReSharper is a .NET coding add-in 28 | _ReSharper*/ 29 | 30 | # TeamCity is a build add-in 31 | _TeamCity* 32 | 33 | # Folders created by Visual Studio Code 34 | *.vscode/ 35 | 36 | # Backup files created by Notepad++ and other applications 37 | *.orig 38 | 39 | # Windows image file caches 40 | Thumbs.db 41 | ehthumbs.db -------------------------------------------------------------------------------- /DeploymentReadinessChecker.psd1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathieuBuisson/DeploymentReadinessChecker/af6dce5b7c3345bd758268280612226a9f9db61f/DeploymentReadinessChecker.psd1 -------------------------------------------------------------------------------- /DeploymentReadinessChecker.psm1: -------------------------------------------------------------------------------- 1 | #Requires -Version 4 2 | #Requires -Modules 'Pester' 3 | 4 | Function Test-DeploymentReadiness { 5 | 6 | <# 7 | .SYNOPSIS 8 | Validates that one or more computers meet the prerequisites for a software deployment/upgrade. 9 | 10 | .DESCRIPTION 11 | Validates that one or more computers meet the prerequisites for a software deployment/upgrade. 12 | It generates a NUnit-style test result file for each computer and creates a visual, dynamic HTLM report encompassing data from all the test results. 13 | The list of computers to check is specified via the ComputerName parameter. 14 | 15 | The deployment or upgrade prerequisites are specified in a Pester-based validation script located in the sub-directory \ReadinessValidationScript. 16 | Test-DeploymentReadiness can only invoke one validation script at a time, even if there are multiple scripts named *.Tests.ps1 in the ReadinessValidationScript sub-directory. 17 | 18 | .PARAMETER ComputerName 19 | To specify one or more computers against which the prerequisites checks will be performed. 20 | 21 | If the validation script has a ComputerName parameter, the function passes one computer at a time to its ComputerName parameter, via the Script parameter of Invoke-Pester. 22 | 23 | .PARAMETER Credential 24 | To specify the credentials to connect remotely to the target computers. 25 | 26 | If the validation script has a Credential parameter, the function passes the value of its own Credential parameter to the validation script, via the Script parameter of Invoke-Pester. 27 | 28 | .PARAMETER OutputPath 29 | To specify in which directory the output test results files and the summary report should be located. 30 | If the directory doesn't exist, it will be created. 31 | If not specified, the defaut output path is the current directory. 32 | 33 | .PARAMETER TestParameters 34 | If the test script used to validate the prerequisites take parameters, their names and values can be specified as a hashtable via this parameter. 35 | Then, the function will pass these into the Script parameter of Invoke-Pester, when calling the validation script. 36 | To see the format of the hashtable for this parameter, please refer to the examples by running : Get-Help Test-DeploymentReadiness -Examples 37 | 38 | .PARAMETER Tag 39 | If the Pester validation script contains Describe blocks with tags, only the tests in Describe blocks with the specified Tag parameter value(s) are run. 40 | Wildcard characters and Tag values that include spaces or whitespace characters are not supported. 41 | 42 | .PARAMETER ExcludeTag 43 | If the Pester validation script contains Describe blocks with tags, tests in Describe blocks with the specified Tag parameter values are omitted. 44 | Wildcard characters and Tag values that include spaces or whitespace characters are not supported. 45 | 46 | Just like the ExcludeTag parameter of Invoke-Pester, when you specify multiple ExcludeTag values, this omits tests that have any of the listed tags (it ORs the tags). 47 | 48 | .PARAMETER ValidationScript 49 | This is a dynamic parameter which is made available (and mandatory) whenever there is more than one test script in the sub-folder \ReadinessValidationScript\. 50 | This is because Test-DeploymentReadiness can only invoke one validation script at a time, so if there is more than one, the user has to specify which one. 51 | 52 | This parameter expects the name (not the full path) of one of the test file present in \ReadinessValidationScript\. 53 | If no value is specified when there is more than one validation script available, the error message will tell the user what are the possible values. 54 | (See the last example in the Examples section of the help.) 55 | 56 | .EXAMPLE 57 | Test-DeploymentReadiness -ComputerName (Get-Content .\Computers_List.txt) -Credential (Get-Credential) -OutputPath $env:USERPROFILE\Desktop\DeploymentReadinessReport 58 | 59 | Validates that all the computers with the name listed in the file Computers_list.txt meet the prerequisites specified in a validation script located in the sub-directory \ReadinessValidationScript. 60 | 61 | .EXAMPLE 62 | $TestParams = @{ DeploymentServerName = $DeploymentServerName; ManagementServerName = $ManagementServerName } 63 | Test-DeploymentReadiness -ComputerName 'Server1','Server2' -Credential (Get-Credential) -TestParameters $TestParams 64 | 65 | Validates that all the computers with the name listed in the file Computers_list.txt meet the prerequisites specified in a validation script located in the sub-directory \ReadinessValidationScript. 66 | It uses a hashtable ($TestParams) to pass parameter names and values to the validation script. 67 | 68 | .EXAMPLE 69 | 'Computer1','Computer2','Computer3' | Test-DeploymentReadiness -Credential (Get-Credential) -OutputPath $env:USERPROFILE\Desktop\DeploymentReadinessReport 70 | 71 | Validates that all the computers specified via pipeline input meet the prerequisites specified in a validation script located in the sub-directory \ReadinessValidationScript. 72 | 73 | .EXAMPLE 74 | Test-DeploymentReadiness -ComputerName (Get-Content .\Computers_List.txt) -Credential (Get-Credential) -OutputPath $env:USERPROFILE\Desktop\DeploymentReadinessReport 75 | 76 | cmdlet Test-DeploymentReadiness at command pipeline position 1 77 | Supply values for the following parameters: 78 | (Type !? for Help.) 79 | ValidationScript: 80 | Test-DeploymentReadiness : Cannot validate argument on parameter 81 | 'ValidationScript'. The argument "" does not belong to the set 82 | "ClientDeployment.Tests.ps1,Example.Tests.ps1" specified by the ValidateSet 83 | attribute. Supply an argument that is in the set and then try the command again. 84 | At line:1 char:1 85 | + Test-DeploymentReadiness -ComputerName 'Devops-test-dscnuc' -OutputPa ... 86 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 87 | + CategoryInfo : InvalidData: (:) [Test-DeploymentReadiness], ParameterBindingValidationException 88 | + FullyQualifiedErrorId : ParameterArgumentValidationError,Test-DeploymentReadiness 89 | 90 | 91 | In this case, there is more than one validation script in the sub-folder \ReadinessValidationScript\, so the user has to specify the name of the validation script via the ValidationScript parameter. 92 | Note that the error message provides the set of possible values ("ClientDeployment.Tests.ps1" and "Example.Tests.ps1", here). 93 | 94 | .NOTES 95 | Author : Mathieu Buisson 96 | 97 | .LINK 98 | https://github.com/MathieuBuisson/DeploymentReadinessChecker 99 | #> 100 | 101 | [cmdletbinding()] 102 | param( 103 | [Parameter(ValueFromPipeline=$True, Mandatory=$True, Position=0)] 104 | [string[]]$ComputerName, 105 | 106 | [Parameter(Position=1)] 107 | [pscredential]$Credential, 108 | 109 | [Parameter(Position=2)] 110 | [string]$OutputPath = $($pwd.ProviderPath), 111 | 112 | [Parameter(Position=3)] 113 | [hashtable]$TestParameters, 114 | 115 | [Parameter(Position=4)] 116 | [Alias('Tags')] 117 | [string[]]$Tag, 118 | 119 | [Parameter(Position=5)] 120 | [Alias('ExcludeTags')] 121 | [string[]]$ExcludeTag 122 | ) 123 | DynamicParam { 124 | # The ValidationScript parameter is made available (and mandatory) only there is more than one test script in the sub-folder \ReadinessValidationScript\. 125 | If ( (Get-ChildItem -Path "$PSScriptRoot\ReadinessValidationScript\" -Filter '*.Tests.ps1').Count -gt 1 ) { 126 | 127 | $ParameterName = 'ValidationScript' 128 | 129 | # Creating a parameter dictionary 130 | $RuntimeParameterDictionary = New-Object -TypeName System.Management.Automation.RuntimeDefinedParameterDictionary 131 | 132 | # Creating an empty collection of parameter attributes 133 | $AttributeCollection = New-Object -TypeName System.Collections.ObjectModel.Collection[System.Attribute] 134 | 135 | # Setting parameter attributes and values 136 | $ValidationScriptAttribute = New-Object -TypeName System.Management.Automation.ParameterAttribute 137 | $ValidationScriptAttribute.Mandatory = $True 138 | $ValidationScriptAttribute.Position = 6 139 | $ValidationScriptAttribute.HelpMessage = "There was more than one test script found in $PSScriptRoot\ReadinessValidationScript\. `r`nPlease specify the name of the test script to use. `r`nTip : Use Tab completion to see the possible script names." 140 | 141 | # Adding the parameter attributes to the attributes collection 142 | $AttributeCollection.Add($ValidationScriptAttribute) 143 | 144 | # Generating dynamic values for a ValidateSet 145 | $SetValues = Get-ChildItem "$PSScriptRoot\ReadinessValidationScript" -Filter '*.Tests.ps1' | Select-Object -ExpandProperty Name 146 | $ValidateSetAttribute = New-Object -TypeName System.Management.Automation.ValidateSetAttribute($SetValues) 147 | 148 | # Adding the ValidateSet to the attributes collection 149 | $AttributeCollection.Add($ValidateSetAttribute) 150 | 151 | # Creating the dynamic parameter 152 | $RuntimeParameter = New-Object -TypeName System.Management.Automation.RuntimeDefinedParameter($ParameterName, [string], $AttributeCollection) 153 | $RuntimeParameterDictionary.Add($ParameterName, $RuntimeParameter) 154 | return $RuntimeParameterDictionary 155 | } 156 | } 157 | 158 | Begin { 159 | 160 | If ( -not(Test-Path -Path $OutputPath) ) { 161 | New-Item -ItemType Directory -Path $OutputPath -Force 162 | } 163 | 164 | # Checking if the validation script has a ComputerName parameter 165 | If ( $PSBoundParameters.ContainsKey('ValidationScript') ) { 166 | $ValidationScriptFile = Join-Path -Path "$PSScriptRoot\ReadinessValidationScript" -ChildPath $PSBoundParameters.ValidationScript 167 | } 168 | Else { 169 | $ValidationScriptFile = (Get-ChildItem -Path "$PSScriptRoot\ReadinessValidationScript\" -Filter '*.Tests.ps1').FullName 170 | } 171 | Write-Verbose "The validation script file is : $ValidationScriptFile" 172 | 173 | $ScriptInfo = Get-Command $ValidationScriptFile 174 | [System.Boolean]$HasComputerNameParameter = $ScriptInfo.Parameters.Keys -contains 'ComputerName' 175 | Write-Verbose "Does the Pester validation script have a ComputerName parameter ? $($HasComputerNameParameter)." 176 | 177 | # Checking if credentials to connect to target computers were specified 178 | If ( $PSBoundParameters.ContainsKey('Credential') ) { 179 | $CredentialSpecified = $True 180 | } 181 | 182 | # Checking if the validation script has a Credential parameter 183 | [System.Boolean]$HasCredentialParameter = $ScriptInfo.Parameters.Keys -contains 'Credential' 184 | Write-Verbose "Does the Pester validation script have a Credential parameter ? $($HasCredentialParameter)." 185 | 186 | # Setting tag filtering parameters to pass to Invoke-Pester if the Tag or ExcludeTag parameter is specified 187 | If ( $PSBoundParameters.ContainsKey('Tag') -or $PSBoundParameters.ContainsKey('ExcludeTag') ) { 188 | 189 | [hashtable]$TagFilteringParameters = @{} 190 | Write-Verbose 'Tag filtering is ON.' 191 | 192 | If ( $PSBoundParameters.ContainsKey('Tag') ) { 193 | $TagFilteringParameters.Add('Tag', $Tag) 194 | } 195 | If ( $PSBoundParameters.ContainsKey('ExcludeTag') ) { 196 | $TagFilteringParameters.Add('ExcludeTag', $ExcludeTag) 197 | } 198 | } 199 | } 200 | Process { 201 | 202 | # If the validation script has a Credential parameter, the function passes the value of 203 | # its own Credential parameter to the validation script, via the Script parameter of Invoke-Pester. 204 | If ( $CredentialSpecified -and $HasCredentialParameter ) { 205 | 206 | If ( $PSBoundParameters.ContainsKey('TestParameters') ) { 207 | If ( $TestParameters.Credential ) { 208 | $TestParameters.Credential = $Credential 209 | } 210 | Else { 211 | $TestParameters.Add('Credential', $Credential) 212 | } 213 | } 214 | Else { 215 | $TestParameters = @{ Credential = $Credential } 216 | } 217 | } 218 | 219 | Foreach ( $Computer in $ComputerName ) { 220 | 221 | # Cleaning up any leading or trailing space 222 | $Computer = $Computer.Trim() 223 | 224 | # If the validation script has a ComputerName parameter, the function passes one computer at a 225 | # time to the validation script's ComputerName parameter, via the Script parameter of Invoke-Pester. 226 | If ( $HasComputerNameParameter ) { 227 | 228 | If ( $TestParameters ) { 229 | If ( $TestParameters.ComputerName ) { 230 | $TestParameters.ComputerName = $Computer 231 | } 232 | Else { 233 | $TestParameters.Add('ComputerName', $Computer) 234 | } 235 | } 236 | Else { 237 | $TestParameters = @{ ComputerName = $Computer } 238 | } 239 | } 240 | 241 | # Building the hashtable to pass parameters to the Pester validation script via the Script parameter of Invoke-Pester 242 | If ( $TestParameters ) { 243 | Foreach ( $Key in $TestParameters.Keys ) { 244 | Write-Verbose "Parameter passed to the validation script. Key : $Key, Value : $($TestParameters.$Key)" 245 | } 246 | 247 | $ScriptParameters = @{ 248 | Path = $ValidationScriptFile 249 | Parameters = $TestParameters 250 | } 251 | } 252 | Else { 253 | $ScriptParameters = @{ 254 | Path = $ValidationScriptFile 255 | } 256 | } 257 | 258 | Write-Verbose "Running Pester validation script against computer : $Computer" 259 | If ( $TagFilteringParameters ) { 260 | Invoke-Pester -Script $ScriptParameters -OutputFile "$OutputPath\$Computer.xml" -OutputFormat NUnitXml @TagFilteringParameters 261 | } 262 | Else { 263 | Invoke-Pester -Script $ScriptParameters -OutputFile "$OutputPath\$Computer.xml" -OutputFormat NUnitXml 264 | } 265 | } 266 | } 267 | End { 268 | Invoke-ReportUnit -OutputPath $OutputPath 269 | } 270 | } 271 | 272 | # Wrapper function to call ReportUnit.exe, this is mainly to be able to mock ReportUnit calls 273 | Function Invoke-ReportUnit ($OutputPath) { 274 | 275 | $ReportUnitPath = "$PSScriptRoot\ReportUnit\ReportUnit.exe" 276 | $Null = & $ReportUnitPath $OutputPath 277 | If ( $LASTEXITCODE -eq 0 ) { 278 | Write-Host "`r`nThe deployment readiness report has been successfully created." 279 | Write-Host "To view the report, please open the following file : $(Join-Path -Path $OutputPath -ChildPath 'Index.html')" 280 | 281 | # It maybe be useful to output the file containing the overview report to the pipeline, in case the user wants to do something with it. 282 | Get-ChildItem -Path (Join-Path -Path $OutputPath -ChildPath 'Index.html') 283 | } 284 | Else { 285 | Write-Error "An error occurred when ReportUnit was generating HTML reports from the Pester test results. To troubleshoot this, try running '$PSScriptRoot\ReportUnit\ReportUnit.exe' manually to see the actual error message." 286 | } 287 | } 288 | 289 | New-Alias -Name 'tdr' -Value 'Test-DeploymentReadiness' 290 | Export-ModuleMember -Function 'Test-DeploymentReadiness' -Alias 'tdr' -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Mathieu BUISSON 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DeploymentReadinessChecker 2 | 3 | [![Build status](https://ci.appveyor.com/api/projects/status/w6dha583tp0gkiio/branch/master?svg=true)](https://ci.appveyor.com/project/MathieuBuisson/deploymentreadinesschecker/branch/master) [![Coverage Status](https://coveralls.io/repos/github/MathieuBuisson/DeploymentReadinessChecker/badge.svg?branch=master)](https://coveralls.io/github/MathieuBuisson/DeploymentReadinessChecker?branch=master) [![Documentation Status](https://readthedocs.org/projects/deploymentreadinesschecker/badge/?version=latest)](http://deploymentreadinesschecker.readthedocs.io/en/latest/?badge=latest) 4 | 5 | 6 | Pester-based tool to validate that a (potentially large) number of machines meet the prerequisites for a software deployment/upgrade. 7 | It generates a NUnit-style test result file for each target machine and creates a visual, dynamic HTLM report encompassing data from all the test results, for example : 8 | 9 | 10 | ![Image of HTML Report](https://i0.wp.com/theshellnut.com/wp-content/uploads/2016/08/Overview-Report.png) 11 | 12 | 13 | This module contains 1 cmdlet : **Test-DeploymentReadiness**. 14 | It requires PowerShell version 4 (or later). 15 | 16 | 17 | ## Test-DeploymentReadiness : 18 | 19 | 20 | Validates that one or more computers meet the prerequisites for a software deployment/upgrade. 21 | It generates a NUnit-style test result file for each computer and creates a visual, dynamic HTLM report 22 | encompassing data from all the test results. 23 | 24 | The list of computers to check is specified via the ComputerName parameter. 25 | 26 | The deployment or upgrade prerequisites are specified in a Pester-based validation script located in the 27 | sub-directory \ReadinessValidationScript. 28 | Test-DeploymentReadiness can only invoke one validation script at a time, even if there are multiple scripts named 29 | *.Tests.ps1 in the ReadinessValidationScript sub-directory. 30 | 31 | 32 | ### Parameters : 33 | 34 | 35 | **ComputerName :** To specify one or more computers against which the prerequisites checks will be performed. 36 | 37 | If the validation script has a ComputerName parameter, the function passes one computer at a time to its ComputerName parameter, via the Script parameter of Invoke-Pester. 38 | 39 | 40 | **Credential :** To specify the credentials to connect remotely to the target computers. 41 | 42 | If the validation script has a Credential parameter, the function passes the value of its own Credential parameter to the validation script, via the Script parameter of Invoke-Pester. 43 | 44 | 45 | **OutputPath :** To specify in which directory the output test results files and the summary report should be located. 46 | If the directory doesn't exist, it will be created. 47 | If not specified, the defaut output path is the current directory. 48 | If not specified, it defaults to $($pwd.ProviderPath) . 49 | 50 | 51 | **TestParameters :** If the test script used to validate the prerequisites take parameters, their names and values can be specified as a hashtable via this parameter. 52 | Then, the function will pass these into the Script parameter of Invoke-Pester, when calling the validation script. 53 | To see the format of the hashtable for this parameter, please refer to the examples by running : Get-Help Test-DeploymentReadiness -Examples 54 | 55 | 56 | **Tag :** If the Pester validation script contains Describe blocks with tags, only the tests in Describe blocks with the specified Tag parameter value(s) are run. 57 | Wildcard characters and Tag values that include spaces or whitespace characters are not supported. 58 | 59 | 60 | **ExcludeTag :** If the Pester validation script contains Describe blocks with tags, tests in Describe blocks with the specified Tag parameter values are omitted. 61 | Wildcard characters and Tag values that include spaces or whitespace characters are not supported. 62 | 63 | Just like the ExcludeTag parameter of Invoke-Pester, when you specify multiple ExcludeTag values, this omits tests that have any of the listed tags (it ORs the tags). 64 | 65 | 66 | **ValidationScript :** This is a dynamic parameter which is made available (and mandatory) whenever there is more than one test script in the sub-folder \ReadinessValidationScript\. 67 | This is because Test-DeploymentReadiness can only invoke one validation script at a time, so if there is more than one, the user has to specify which one. 68 | 69 | This parameter expects the name (not the full path) of one of the test file present in \ReadinessValidationScript\. 70 | If no value is specified when there is more than one validation script available, the error message will tell the user what are the possible values. 71 | (See the last example in the Examples section of the help.) 72 | -------------------------------------------------------------------------------- /ReadinessValidationScript/Example.Tests.ps1: -------------------------------------------------------------------------------- 1 | #Requires -Modules 'Pester' 2 | 3 | <# 4 | PURPOSE: Pester script to validate that a machine meets the prerequisites for a software deployment/upgrade. 5 | It generates a NUnit-style test result file for each computer and a summary report in HTML format. 6 | This script is designed to be run remotely (not from the target machine). 7 | #> 8 | [CmdletBinding()] 9 | Param( 10 | [Parameter(Mandatory=$True)] 11 | [ValidateScript({ Test-Connection -ComputerName $_ -Quiet })] 12 | [string]$ComputerName, 13 | 14 | [Parameter(Mandatory=$True)] 15 | [pscredential]$Credential, 16 | 17 | [Parameter(Mandatory=$True)] 18 | [string]$DeploymentServerName, 19 | 20 | [Parameter(Mandatory=$True)] 21 | [string]$ManagementServerName 22 | ) 23 | 24 | $RemoteSession = New-PSSession -ComputerName $ComputerName -Credential $Credential 25 | 26 | Describe 'Hardware prerequisites' -Tag 'Hardware' { 27 | 28 | It 'Has at least 4096 MB of total RAM' { 29 | 30 | Invoke-Command -Session $RemoteSession { 31 | (Get-CimInstance -ClassName Win32_PhysicalMemory).Capacity / 1MB } | 32 | Should Not BeLessThan 4096 33 | } 34 | } 35 | Describe 'Networking prerequisites' -Tag 'Networking' { 36 | 37 | It 'Can ping the Management server by name' { 38 | 39 | Invoke-Command -Session $RemoteSession { param($ManagementServerName) 40 | Test-Connection -ComputerName $ManagementServerName -Quiet } -ArgumentList $ManagementServerName | 41 | Should Be $True 42 | } 43 | It 'Can ping the Deployment server by name' { 44 | 45 | Invoke-Command -Session $RemoteSession { param($DeploymentServerName) 46 | Test-Connection -ComputerName $DeploymentServerName -Quiet } -ArgumentList $DeploymentServerName | 47 | Should Be $True 48 | } 49 | It 'Has connectivity to the Management server on TCP port 80' { 50 | 51 | Invoke-Command -Session $RemoteSession { param($ManagementServerName) 52 | (Test-NetConnection -ComputerName $ManagementServerName -CommonTCPPort HTTP).TcpTestSucceeded } -ArgumentList $ManagementServerName | 53 | Should Be $True 54 | } 55 | It 'Has the firewall profile set to "Domain" or "Private"' { 56 | 57 | Invoke-Command -Session $RemoteSession { 58 | $FirewallProfile = (Get-NetConnectionProfile)[0].NetworkCategory.ToString(); 59 | $FirewallProfile -eq 'Domain' -or $FirewallProfile -eq 'Private' } | 60 | Should Be $True 61 | } 62 | } 63 | Describe 'OS and runtime prerequisites' -Tag 'OS' { 64 | 65 | It 'Has the Windows Update KB2883200' { 66 | 67 | Invoke-Command -Session $RemoteSession { 68 | Get-HotFix -Id KB2883200 -ErrorAction SilentlyContinue } | 69 | Should Not BeNullOrEmpty 70 | } 71 | It 'Has the required version of the C++ 2010 runtime' { 72 | 73 | Invoke-Command -Session $RemoteSession { 74 | Get-CimInstance -ClassName Win32_Product -Filter "Name='Microsoft Visual C++ 2010 x64 Redistributable - 10.0.40219'" } | 75 | Should Not BeNullOrEmpty 76 | } 77 | It 'Has the shell set to "explorer.exe" at the global level (HKLM)' { 78 | 79 | Invoke-Command -Session $RemoteSession { 80 | (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon').Shell } | 81 | Should Be 'explorer.exe' 82 | } 83 | } 84 | Describe 'PowerShell prerequisites' { 85 | 86 | It 'Has the execution policy set to "RemoteSigned" or "Unrestricted"' { 87 | 88 | Invoke-Command -Session $RemoteSession { 89 | $Policy = (Get-ExecutionPolicy); $Policy -eq 'RemoteSigned' -or $Policy -eq 'Unrestricted' } | 90 | Should Be $True 91 | } 92 | It 'Has PowerShell version 4.0 or later' { 93 | 94 | Invoke-Command -Session $RemoteSession { 95 | $PSVersionTable.PSVersion -ge [System.Version]'4.0' } | 96 | Should Be $True 97 | } 98 | It 'Has the PackageManagement module installed' { 99 | 100 | Invoke-Command -Session $RemoteSession { 101 | Get-Module -Name 'PackageManagement' -ListAvailable } | 102 | Should Not BeNullOrEmpty 103 | } 104 | It 'Has Chocolatey in its registered package sources for the provider "Chocolatey"' { 105 | Invoke-Command -Session $RemoteSession { 106 | Get-PackageSource -Name Chocolatey -ProviderName Chocolatey } | 107 | Should Not BeNullOrEmpty 108 | } 109 | } -------------------------------------------------------------------------------- /ReportUnit/LICENSE: -------------------------------------------------------------------------------- 1 | ### License 2 | 3 | Copyright (c) 2015 Anshoo Arora (Relevant Codes) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /ReportUnit/ReportUnit.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MathieuBuisson/DeploymentReadinessChecker/af6dce5b7c3345bd758268280612226a9f9db61f/ReportUnit/ReportUnit.exe -------------------------------------------------------------------------------- /Tests/Unit/DeploymentReadinessChecker.Tests.ps1: -------------------------------------------------------------------------------- 1 | Import-Module "$($PSScriptRoot)\..\..\DeploymentReadinessChecker.psd1" -Force 2 | $ModuleName = 'DeploymentReadinessChecker' 3 | $OutputPath = 'TestDrive:\OutputFolder' 4 | $ComputerNames = 'Computer1','Computer2','Computer3' 5 | $ScriptInfo = Get-Command (Get-ChildItem -Path "$PSScriptRoot\..\..\ReadinessValidationScript\" -Filter '*.Tests.ps1')[0].FullName 6 | 7 | Describe 'General Module behaviour' { 8 | 9 | $ModuleInfo = Get-Module -Name $ModuleName 10 | 11 | It 'Exports only the function "Test-DeploymentReadiness"' { 12 | 13 | $ModuleInfo.ExportedFunctions.Values.Name | 14 | Should Be 'Test-DeploymentReadiness' 15 | } 16 | It 'Exports only the alias "tdr"' { 17 | 18 | $ModuleInfo.ExportedAliases.Values.Name | 19 | Should Be 'tdr' 20 | } 21 | It 'The only required module should be Pester' { 22 | 23 | $ModuleInfo.RequiredModules.Name | 24 | Should Be 'Pester' 25 | } 26 | } 27 | Describe 'Test-DeploymentReadiness' { 28 | 29 | Context 'Parameters behaviour' { 30 | 31 | Mock -ModuleName $ModuleName Invoke-Pester { } 32 | Mock -ModuleName $ModuleName Get-ChildItem { } -ParameterFilter {$Path -eq "$OutputPath\Index.html"} 33 | Mock -ModuleName $ModuleName Invoke-ReportUnit { } 34 | 35 | It "If the directory specified via the parameter 'OutputPath' doesn't exist, it should create it" { 36 | 37 | Test-DeploymentReadiness -ComputerName $ComputerNames[0] -OutputPath $OutputPath 38 | Test-Path -Path $OutputPath -PathType Container | 39 | Should Be $True 40 | } 41 | It 'Should call Invoke-Pester once per Computer specified via the ComputerName parameter' { 42 | 43 | Test-DeploymentReadiness -ComputerName $ComputerNames -OutputPath $OutputPath 44 | Assert-MockCalled Invoke-Pester -Exactly 3 -Scope It -ModuleName $ModuleName 45 | } 46 | It 'Should call Invoke-Pester once per Computer specified via pipeline input' { 47 | 48 | $ComputerNames | Test-DeploymentReadiness -OutputPath $OutputPath 49 | Assert-MockCalled Invoke-Pester -Exactly 3 -Scope It -ModuleName $ModuleName 50 | } 51 | It 'If the Credential parameter is specified, it should add it into the Script parameter of Invoke-Pester' { 52 | 53 | $Password = ConvertTo-SecureString 'TestPasswd' -AsPlainText -Force 54 | $TestCred = New-Object System.Management.Automation.PSCredential ('TestUser', $Password) 55 | 56 | Test-DeploymentReadiness -ComputerName $ComputerNames -OutputPath $OutputPath -Credential $TestCred 57 | Assert-MockCalled Invoke-Pester -Scope It -ModuleName $ModuleName -ParameterFilter { 58 | $Script.Parameters.Credential -eq $TestCred 59 | } 60 | } 61 | It 'If the TestParameters parameter is specified, it should add all its key-value pairs into the Script parameter of Invoke-Pester' { 62 | 63 | $TestParams = @{PesterScriptParam1 = 'Param1Value' 64 | PesterScriptParam2 = 'Param2Value' 65 | } 66 | Test-DeploymentReadiness -ComputerName $ComputerNames[0] -TestParameters $TestParams 67 | Foreach ( $Key in $TestParams.Keys ) { 68 | Assert-MockCalled Invoke-Pester -Scope It -ModuleName $ModuleName -ParameterFilter { 69 | $Script.Parameters.$Key -eq $TestParams.$Key 70 | } 71 | } 72 | } 73 | It 'Should pass all values in the Tag parameter to Invoke-Pester' { 74 | 75 | $TestTags = 'Tag1','Tag2','Tag3' 76 | Test-DeploymentReadiness -ComputerName $ComputerNames[0] -Tag $TestTags 77 | Foreach ( $TestTag in $TestTags ) { 78 | Assert-MockCalled Invoke-Pester -Scope It -ModuleName $ModuleName -ParameterFilter { 79 | $Tag -contains $TestTag 80 | } 81 | } 82 | } 83 | It 'Should pass all values in the ExcludeTag parameter to Invoke-Pester' { 84 | 85 | $TestExcludeTags = 'ExcludeTag1','ExcludeTag2' 86 | Test-DeploymentReadiness -ComputerName $ComputerNames[0] -ExcludeTag $TestExcludeTags 87 | Foreach ( $TestExcludeTag in $TestExcludeTags ) { 88 | Assert-MockCalled Invoke-Pester -Scope It -ModuleName $ModuleName -ParameterFilter { 89 | $ExcludeTag -contains $TestExcludeTag 90 | } 91 | } 92 | } 93 | } 94 | Context 'General Function behaviour' { 95 | 96 | Mock -ModuleName $ModuleName Invoke-Pester { } 97 | Mock -ModuleName $ModuleName Get-ChildItem { } -ParameterFilter {$Path -eq "$OutputPath\Index.html"} 98 | Mock -ModuleName $ModuleName Invoke-ReportUnit { } 99 | 100 | It 'Should call ReportUnit only once, even when there are multiple computers' { 101 | 102 | Test-DeploymentReadiness -ComputerName $ComputerNames -OutputPath $OutputPath 103 | Assert-MockCalled Invoke-ReportUnit -Exactly 1 -Scope It -ModuleName $ModuleName 104 | } 105 | It 'Should call ReportUnit only once, even with multiple computers specified via pipeline input' { 106 | 107 | $ComputerNames | Test-DeploymentReadiness -OutputPath $OutputPath 108 | Assert-MockCalled Invoke-ReportUnit -Exactly 1 -Scope It -ModuleName $ModuleName 109 | } 110 | } 111 | } 112 | 113 | Describe 'Dynamic parameter "ValidationScript"' { 114 | 115 | Mock -ModuleName $ModuleName Invoke-Pester { } 116 | Mock -ModuleName $ModuleName Get-ChildItem { } -ParameterFilter {$Path -eq "$OutputPath\Index.html"} 117 | Mock -ModuleName $ModuleName Get-ChildItem { 118 | [PSCustomObject]@{ FullName = 'TestDrive:\Example1.Tests.ps1'; Name = 'Example1.Tests.ps1' }, 119 | [PSCustomObject]@{ FullName = 'TestDrive:\Example2.Tests.ps1'; Name = 'Example2.Tests.ps1' } 120 | } -ParameterFilter {$Path -like '*ReadinessValidationScript*' -and $Filter -eq '*.Tests.ps1'} 121 | Mock -ModuleName $ModuleName Invoke-ReportUnit { } 122 | Mock -ModuleName $ModuleName Get-Command { $ScriptInfo } 123 | 124 | It "Should throw when the value for the ValidationScript doesn't belong to the ValidateSet" { 125 | 126 | {Test-DeploymentReadiness -ComputerName $ComputerNames[0] -ValidationScript 'NotThere.Tests.ps1'} | 127 | Should Throw 'does not belong to the set "Example1.Tests.ps1,Example2.Tests.ps1"' 128 | } 129 | It 'Should call Invoke-Pester with the validation script specified via the ValidationScript parameter' { 130 | 131 | Test-DeploymentReadiness -ComputerName $ComputerNames[0] -ValidationScript 'Example1.Tests.ps1' 132 | Assert-MockCalled Invoke-Pester -Scope It -ModuleName $ModuleName -ParameterFilter { 133 | $Script.Path -like '*\ReadinessValidationScript\Example1.Tests.ps1' 134 | } 135 | } 136 | } 137 | 138 | Describe 'Invoke-ReportUnit' { 139 | 140 | InModuleScope $ModuleName { 141 | 142 | $OutputPath = 'TestDrive:\OutputFolder' 143 | 144 | Mock Invoke-Pester { } 145 | Mock Get-ChildItem { } -ParameterFilter {$Path -eq "$OutputPath\Index.html"} 146 | Mock Write-Host { } 147 | 148 | It 'Should call Get-ChildItem on "$OutputPath\Index.html"' { 149 | 150 | Invoke-ReportUnit -OutputPath $OutputPath 151 | Assert-MockCalled Get-ChildItem -Scope It -ParameterFilter { 152 | $Path -eq "$OutputPath\Index.html" 153 | } 154 | } 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 1.0.{build} 2 | 3 | os: WMF 5 4 | 5 | # Skip on updates to the readme 6 | skip_commits: 7 | message: /readme*/ 8 | 9 | environment: 10 | CA_Key: 11 | secure: 5RSsazuNC6hRPAKulKD6F8TPlNJpX3tTwclQCDhILMS6nHbMTZYhX8hXu1tpPM1+ 12 | 13 | install: 14 | - ps: Write-Host "Build version :` $env:APPVEYOR_BUILD_VERSION" 15 | - ps: Write-Host "Branch :` $env:APPVEYOR_REPO_BRANCH" 16 | - ps: Install-PackageProvider -Name NuGet -Force 17 | - ps: Set-PSRepository -Name PSGallery -InstallationPolicy Trusted 18 | - ps: Install-Module Coveralls -Scope CurrentUser -Force 19 | - ps: Import-Module Coveralls 20 | - ps: Install-Module -Name Pester -Force 21 | - ps: Install-Module PsScriptAnalyzer -Force 22 | 23 | build: false 24 | 25 | test_script: 26 | - ps: | 27 | $TestsUploadUrl = "https://ci.appveyor.com/api/testresults/nunit/$($env:APPVEYOR_JOB_ID)" 28 | $TestsOutput = Invoke-Pester -Script '.\Tests' -CodeCoverage '.\DeploymentReadinessChecker.psm1' -OutputFile TestResults.xml -PassThru 29 | (New-Object 'System.Net.WebClient').UploadFile($TestsUploadUrl, (Resolve-Path .\TestResults.xml)) 30 | $FailedCount = $UnitTestsOutput.FailedCount 31 | If ($FailedCount -gt 0) { 32 | Add-AppveyorMessage -Message "$($FailedCount) unit test(s) failed." 33 | 34 | # Failing the build 35 | Throw "Build failed because $($FailedCount) unit test(s) failed" 36 | } 37 | $Coverage = Format-Coverage -PesterResults $TestsOutput -CoverallsApiToken $ENV:CA_Key -BranchName $ENV:APPVEYOR_REPO_BRANCH 38 | Publish-Coverage -Coverage $Coverage 39 | 40 | - ps: | 41 | Add-AppveyorTest -Name "PsScriptAnalyzer" -Outcome Running 42 | $ScriptAnalyzerResults = Invoke-ScriptAnalyzer -Path $pwd -Severity Error -ErrorAction SilentlyContinue 43 | If ($ScriptAnalyzerResults) { 44 | $ScriptAnalyzerResultString = $ScriptAnalyzerResults | Out-String 45 | Write-Warning $ScriptAnalyzerResultString 46 | Add-AppveyorMessage -Message "PSScriptAnalyzer output contained one or more result(s) with 'Error' severity.` 47 | Check the 'Tests' tab of this build for more details." -Category Error 48 | Update-AppveyorTest -Name "PsScriptAnalyzer" -Outcome Failed -ErrorMessage $ScriptAnalyzerResultString 49 | 50 | # Failing the build 51 | Throw "Build failed" 52 | } 53 | Else { 54 | Update-AppveyorTest -Name "PsScriptAnalyzer" -Outcome Passed 55 | } 56 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # DeploymentReadinessChecker 2 | 3 | 4 | 5 | Pester-based tool to validate that a (potentially large) number of machines meet the prerequisites for a software deployment/upgrade. 6 | It generates a NUnit-style test result file for each target machine and creates a visual, dynamic HTLM report encompassing data from all the test results, for example : 7 | 8 | 9 | ![Image of HTML Report](https://i0.wp.com/theshellnut.com/wp-content/uploads/2016/08/Overview-Report.png) 10 | 11 | 12 | This module contains 1 cmdlet : **Test-DeploymentReadiness**. 13 | It requires PowerShell version 4 (or later). 14 | 15 | 16 | ## Test-DeploymentReadiness : 17 | 18 | 19 | Validates that one or more computers meet the prerequisites for a software deployment/upgrade. 20 | It generates a NUnit-style test result file for each computer and creates a visual, dynamic HTLM report 21 | encompassing data from all the test results. 22 | 23 | The list of computers to check is specified via the ComputerName parameter. 24 | 25 | The deployment or upgrade prerequisites are specified in a Pester-based validation script located in the 26 | sub-directory \ReadinessValidationScript. 27 | Test-DeploymentReadiness can only invoke one validation script at a time, even if there are multiple scripts named 28 | *.Tests.ps1 in the ReadinessValidationScript sub-directory. 29 | 30 | 31 | ### Parameters : 32 | 33 | 34 | **ComputerName :** To specify one or more computers against which the prerequisites checks will be performed. 35 | 36 | If the validation script has a ComputerName parameter, the function passes one computer at a time to its ComputerName parameter, via the Script parameter of Invoke-Pester. 37 | 38 | 39 | **Credential :** To specify the credentials to connect remotely to the target computers. 40 | 41 | If the validation script has a Credential parameter, the function passes the value of its own Credential parameter to the validation script, via the Script parameter of Invoke-Pester. 42 | 43 | 44 | **OutputPath :** To specify in which directory the output test results files and the summary report should be located. 45 | If the directory doesn't exist, it will be created. 46 | If not specified, the defaut output path is the current directory. 47 | If not specified, it defaults to $($pwd.ProviderPath) . 48 | 49 | 50 | **TestParameters :** If the test script used to validate the prerequisites take parameters, their names and values can be specified as a hashtable via this parameter. 51 | Then, the function will pass these into the Script parameter of Invoke-Pester, when calling the validation script. 52 | To see the format of the hashtable for this parameter, please refer to the examples by running : Get-Help Test-DeploymentReadiness -Examples 53 | 54 | 55 | **Tag :** If the Pester validation script contains Describe blocks with tags, only the tests in Describe blocks with the specified Tag parameter value(s) are run. 56 | Wildcard characters and Tag values that include spaces or whitespace characters are not supported. 57 | 58 | 59 | **ExcludeTag :** If the Pester validation script contains Describe blocks with tags, tests in Describe blocks with the specified Tag parameter values are omitted. 60 | Wildcard characters and Tag values that include spaces or whitespace characters are not supported. 61 | 62 | Just like the ExcludeTag parameter of Invoke-Pester, when you specify multiple ExcludeTag values, this omits tests that have any of the listed tags (it ORs the tags). 63 | 64 | 65 | **ValidationScript :** This is a dynamic parameter which is made available (and mandatory) whenever there is more than one test script in the sub-folder \ReadinessValidationScript\. 66 | This is because Test-DeploymentReadiness can only invoke one validation script at a time, so if there is more than one, the user has to specify which one. 67 | 68 | This parameter expects the name (not the full path) of one of the test file present in \ReadinessValidationScript\. 69 | If no value is specified when there is more than one validation script available, the error message will tell the user what are the possible values. 70 | (See the last example in the Examples section of the help.) 71 | 72 | ### Examples : 73 | 74 | 75 | 76 | -------------------------- EXAMPLE 1 -------------------------- 77 | 78 | PS C:\>Test-DeploymentReadiness -ComputerName (Get-Content .\Computers_List.txt) -Credential 79 | (Get-Credential) -OutputPath $env:USERPROFILE\Desktop\DeploymentReadinessReport 80 | 81 | 82 | Validates that all the computers with the name listed in the file Computers_list.txt meet the 83 | prerequisites specified in a validation script located in the sub-directory \ReadinessValidationScript. 84 | 85 | 86 | 87 | 88 | -------------------------- EXAMPLE 2 -------------------------- 89 | 90 | PS C:\>$TestParams = @{ DeploymentServerName = $DeploymentServerName; ManagementServerName = 91 | $ManagementServerName } 92 | 93 | 94 | PS C:\>Test-DeploymentReadiness -ComputerName 'Server1','Server2' -Credential (Get-Credential) -TestParameters 95 | $TestParams 96 | 97 | Validates that all the computers with the name listed in the file Computers_list.txt meet the 98 | prerequisites specified in a validation script located in the sub-directory \ReadinessValidationScript. 99 | It uses a hashtable ($TestParams) to pass parameter names and values to the validation script. 100 | 101 | 102 | 103 | 104 | -------------------------- EXAMPLE 3 -------------------------- 105 | 106 | PS C:\>'Computer1','Computer2','Computer3' | Test-DeploymentReadiness -Credential (Get-Credential) 107 | -OutputPath $env:USERPROFILE\Desktop\DeploymentReadinessReport 108 | 109 | 110 | Validates that all the computers specified via pipeline input meet the prerequisites specified in a 111 | validation script located in the sub-directory \ReadinessValidationScript. 112 | 113 | 114 | 115 | -------------------------- EXAMPLE 4 -------------------------- 116 | 117 | PS C:\>Test-DeploymentReadiness -ComputerName (Get-Content .\Computers_List.txt) -Credential (Get-Credential) 118 | -OutputPath $env:USERPROFILE\Desktop\DeploymentReadinessReport 119 | 120 | 121 | cmdlet Test-DeploymentReadiness at command pipeline position 1 122 | Supply values for the following parameters: 123 | (Type !? for Help.) 124 | ValidationScript: 125 | Test-DeploymentReadiness : Cannot validate argument on parameter 126 | 'ValidationScript'. The argument "" does not belong to the set 127 | "ClientDeployment.Tests.ps1,Example.Tests.ps1" specified by the ValidateSet 128 | attribute. Supply an argument that is in the set and then try the command again. 129 | At line:1 char:1 130 | 131 | \+ Test-DeploymentReadiness -ComputerName 'Devops-test-dscnuc' -OutputPa ... 132 | \+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 133 | \+ CategoryInfo : InvalidData: (:) [Test-DeploymentReadiness], ParameterBindingValidationException 134 | \+ FullyQualifiedErrorId : ParameterArgumentValidationError,Test-DeploymentReadiness 135 | 136 | 137 | 138 | 139 | 140 | In this case, there is more than one validation script in the sub-folder \ReadinessValidationScript\, so the user has 141 | to specify the name of the validation script via the ValidationScript parameter. 142 | Note that the error message provides the set of possible values ("ClientDeployment.Tests.ps1" and "Example.Tests.ps1", 143 | here). 144 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: DeploymentReadinessChecker 2 | repo_url: https://github.com/MathieuBuisson/DeploymentReadinessChecker 3 | site_author: Mathieu Buisson 4 | theme: readthedocs 5 | copyright: "DeploymentReadinessChecker is licensed under the MIT license" 6 | pages: 7 | - Home: index.md 8 | --------------------------------------------------------------------------------