Start-Jojoba.ps1
<#
.SYNOPSIS Parallel processing with test case output and Jenkins integration. .DESCRIPTION For a Jojoba template function this will be the main call in the process {} block. All processing should occur within here. .PARAMETER ScriptBlock The test to carry out. It must use $InputObject or $_. .INPUTS None. All inputs are taken from the host function ($InputObject, Parallel, $_, $JojobaThrottle, $JojobaBatch). Other inputs taken are the calling module name and calling function name. .OUTPUTS A test case object. #> function Start-Jojoba { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ScriptBlock] $ScriptBlock ) begin { } process { # Fill out the base test case, named after parts of the caller $jojoba = [PSCustomObject] @{ Suite = $PSCmdlet.GetVariableValue("MyInvocation").MyCommand.ModuleName Timestamp = Get-Date Time = 0 ClassName = $PSCmdlet.GetVariableValue("MyInvocation").MyCommand.Name Name = $PSCmdlet.GetVariableValue("InputObject") Result = "Pass" Message = New-Object Collections.ArrayList Data = New-Object Collections.ArrayList } # Determine whether we're going to run the test block, or spawn off copies to run in Parallel if (!$PSCmdlet.GetVariableValue("Parallel")) { #region Single-threaded run Write-Verbose "Starting $($jojoba.Name)" try { &$ScriptBlock } catch { # Handle uncaught exceptions as a test block failure. This saves a lot of test code. Write-JojobaFail $_.ToString() Write-JojobaData (Resolve-Error $_ -AsString) } # Calculate other useful information for the test case for use by Jenkins $jojoba.Time = ((Get-Date) - $jojoba.Timestamp).TotalSeconds # Simplify the various outputs if ($jojoba.Message) { $jojoba.Message = $jojoba.Message -join [Environment]::NewLine } if ($jojoba.Data) { $jojoba.Data = $jojoba.Data -join [Environment]::NewLine } # Write out the test case $jojoba #endregion } else { #region Parallel run # These are arguments which will be splatted for use by PoshRSJob $jobArguments = @{ Throttle = $PSCmdlet.GetVariableValue("JojobaThrottle") Batch = $PSCmdlet.GetVariableValue("JojobaBatch") ModulesToImport = @($jojoba.Suite) ScriptBlock = [scriptblock]::Create("`$_ | $($jojoba.ClassName) -Parallel:`$false") } # Add any extra switches and parameters to the scriptblock so they can be passed to the caller. # This can't handle complex objects - those should be piped in instead. $PSCmdlet.GetVariableValue("MyInvocation").BoundParameters.GetEnumerator() | %{ if ($_.Key -ne "InputObject") { if ($_.Value -is [System.Management.Automation.SwitchParameter]) { $jobArguments.ScriptBlock = [scriptblock]::Create("$($jobArguments.ScriptBlock) -$($_.Key):`$$($_.Value)") } else { $jobArguments.ScriptBlock = [scriptblock]::Create("$($jobArguments.ScriptBlock) -$($_.Key) $($_.Value)") } } } Write-Verbose "Scheduling $($jojoba.Name) as $($jobArguments.ScriptBlock)" # Here we can continue to pipe in a complex object, or, revert back to the InputObject, for simplicity @(if ($PSCmdlet.GetVariableValue("_") -and $PSCmdlet.GetVariableValue("_") -isnot [string]) { $PSCmdlet.GetVariableValue("_") } else { $PSCmdlet.GetVariableValue("InputObject") }) | Start-RSJob @jobArguments | Out-Null #endregion } } end { } } |