private/Helper.ps1
Function ProcessRemotelyJob { [CmdletBinding()] param( [Parameter(Mandatory, ValueFromPipeline)] [Object]$InputObject ) foreach($childJob in $InputObject.ChildJobs) { if($childJob.Output.Count -eq 0){ [object] $outputStream = New-Object psobject } else { [object] $outputStream = $childJob.Output | % { $_ } } $errorStream = CopyStreams $childJob.Error $verboseStream = CopyStreams $childJob.Verbose $debugStream = CopyStreams $childJob.Debug $warningStream = CopyStreams $childJob.Warning $progressStream = CopyStreams $childJob.Progress $allStreams = @{ Error = $errorStream Verbose = $verboseStream DebugOutput = $debugStream Warning = $warningStream ProgressOutput = $progressStream } $outputStream = Add-Member -InputObject $outputStream -PassThru -MemberType NoteProperty -Name __Streams -Value $allStreams $outputStream = Add-Member -InputObject $outputStream -PassThru -MemberType ScriptMethod -Name GetError -Value { return $this.__Streams.Error } $outputStream = Add-Member -InputObject $outputStream -PassThru -MemberType ScriptMethod -Name GetVerbose -Value { return $this.__Streams.Verbose } $outputStream = Add-Member -InputObject $outputStream -PassThru -MemberType ScriptMethod -Name GetDebugOutput -Value { return $this.__Streams.DebugOutput } $outputStream = Add-Member -InputObject $outputStream -PassThru -MemberType ScriptMethod -Name GetProgressOutput -Value { return $this.__Streams.ProgressOutput } $outputStream = Add-Member -InputObject $outputStream -PassThru -MemberType ScriptMethod -Name GetWarning -Value { return $this.__Streams.Warning } $outputStream = Add-Member -InputObject $outputStream -PassThru -MemberType NoteProperty -Name RemotelyTarget -Value $childJob.Location if($childJob.State -eq 'Failed'){ $childJob | Receive-Job -ErrorAction SilentlyContinue -ErrorVariable jobError $outputStream.__Streams.Error = $jobError } Write-Output -InputObject $outputStream } } Function ProcessRemotelyOutputToJSON { [CmdletBinding()] param( [Parameter(Mandatory, ValueFromPipeline)] [Object]$InputObject, # Specify this switch to get the raw pester output back for the nodes. [Switch]$Raw ) $NodeName = $InputObject.PSComputerName | Select-Object -Unique $NodeName = $NodeName -replace '\[','' $NodeName = $NodeName -replace '\]','' $output = @{ NodeName = $NodeName; Tests = @( if ($Raw.ISPresent) { $InputObject.TestResult } else { GetFormattedTestResult -TestResult $InputObject.TestResult }) #Status = if ($result.FailedCount) {$False} else {$True}; } $output.Add('Status',$(@($output.Tests.GetEnumerator() | Foreach {$PSItem.Result}) -notcontains $false )) $output | ConvertTo-Json -depth 100 } Function GetFormattedTestResult { [CmdletBinding()] param( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [System.Collections.ArrayList]$testResult ) $outputHashArray = @() $testsGroup = $testResult |Group-Object -Property Describe foreach ($testGroup in $testsGroup) { $result = ($TestGroup.Group | select -ExpandProperty Passed ) -Notcontains $false $outputHashArray += @{ Name = $testGroup.Name Result = $result TestResult = @($testGroup.Group | Where -Property Result -eq 'Failed' | Select -Property Describe, Context, Name, Result, ErrorRecord) } } Write-Output -InputObject $outputHashArray } Function Write-VerboseLog { [CmdletBinding(DefaultParameterSetName='Message')] Param ( # Message to be written to the Verbose Stream [Parameter(ParameterSetName ='Message', Position=0, ValueFromPipeline)] [ValidateNotNullOrEmpty()] [System.String]$Message, # In case of calling this from Catch block pass the Invocation info [Parameter(ParameterSetName='Error', ValueFromPipeline, ValueFromPipelineByPropertyName)] [System.Management.Automation.ErrorRecord]$ErrorInfo ) switch -exact ($PSCmdlet.ParameterSetName) { 'Message' { $parentcallstack = (Get-PSCallStack)[1] # store the parent Call Stack $Functionname = $parentcallstack.FunctionName $LineNo = $parentcallstack.ScriptLineNumber $scriptname = ($parentcallstack.Location -split ':')[0] Write-Verbose -Message "$scriptname - $Functionname - LineNo : $LineNo - $Message" } 'Error' { # In case of error, Error Record is passed and we use that to write key info to verbose stream $Message = $ErrorInfo.Exception.Message $Functionname = $ErrorInfo.InvocationInfo.InvocationName $LineNo = $ErrorInfo.InvocationInfo.ScriptLineNumber $scriptname = $(Split-Path -Path $ErrorInfo.InvocationInfo.ScriptName -Leaf) Write-Verbose -Message "$scriptname - $Functionname - LineNo : $LineNo - $Message" #$PSCmdlet.ThrowTerminatingError($ErrorInfo) #Write-Error -ErrorRecord $ErrorInfo -ErrorAction Stop # throw back the Error record } } } Function Start-RemotelyJobProcessing { [CmdletBinding()] param( [Parameter(Mandatory)] [Object[]]$inputObject ) TRY { $allJobsCompletedHash = @{} $inputObject | Foreach-Object -Process { $allJobsCompletedHash.Add($PSItem, $false) } $cloneJobHash = $allJobsCompletedHash.Clone() do { foreach ($enum in $cloneJobHash.GetEnumerator()) { if ($allJobsCompletedHash[$enum.key]) { # means job was processed Write-VerboseLog -Message "PSRemotely job already processed for Node -> $(($enum.key).Location )" } else { # see if the job finished if ($enum.Key | Where -Property State -In @('Completed','Failed')) { Write-VerboseLog -Message "PSRemotely job completed/failed for Node -> $(($enum.key).Location ) . Processing it now." $enum.Key | ProcessRemotelyJob | ProcessRemotelyOutputToJSOn $allJobsCompletedHash[$enum.key] = $true # set the job processed status to True } } } # induce delay of 2 seconds Write-VerboseLog -Message 'PSRemotely jobs still running, sleep for 5 seconds' Start-Sleep -Seconds 5 } until (@($allJobsCompletedHash.Values) -notcontains $False) } CATCH { Write-VerboseLog -ErrorInfo $PSitem $PSCmdlet.ThrowTerminatingError($_) } } |