Wait-IpsJob.ps1
<# .SYNOPSIS Wait for an Image Portability Service job to complete. .DESCRIPTION Waits for an Image Portability Service (IPS) job to complete. .PARAMETER CustomerId Specifies the customer id of the Citrix customer running this command. .PARAMETER SecureClientId Specifies the client id of the Citrix customer's API client. .PARAMETER SecureSecret Specifies the client secret of the Citrix customer's API client. .PARAMETER JobId Specifies the id of the job to wait for. .PARAMETER PollSeconds Specifies the interval between polls for the job's status. .PARAMETER Deployment Specifies the service address to send the job request to. It defaults to api.layering.cloud.com. This can be used if necessary to send the request to a geo specific deployment such as api.eu.layering.cloud.com. .PARAMETER LogFileDir Specifies the path to the file to log to. The local directory is the default. .PARAMETER LogFileName Specifies the name of the file to log to. .PARAMETER OverwriteLog If specified the log file is overwritten otherwise it is appended to. .PARAMETER Output If specified the cmdlet outputs a PSCustomObject with information about the job including the job's status. .INPUTS PSCustomObject. The output from one of the IPS job starting cmdlets. .OUTPUTS PSCustomObject. Information about the job including the job's status is emitted if -Output is specified. .EXAMPLE PS> Start-IpsAzurePrepareJob ... | Wait-IpsJob Wait for an IPS job using the output from the command which started the job. .EXAMPLE PS> $CitrixCreds = @{ CustomerId = 'a7f4wb1example' SecureClientId = '7fed2a1e-1495-46b7-8fd3-5644764af395' SecureSecret = '9T.3Q~MGlnB6NNgpNUUWrcquVzODrdGK~eXampLe' } PS> Wait-IpsJob @CitrixCreds -JobId fb067a8a-b20a-4889-ba3e-1ec580edd9c5 Wait for an IPS job explicitly providing the Citrix customer credentials and the job id. #> Function Wait-IpsJob { [CmdletBinding()] Param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [string]$CustomerId, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [string]$SecureClientId, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [string]$SecureSecret, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [string]$JobId, [Parameter(Mandatory = $false)] [int]$PollSeconds = 60, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [string]$Deployment, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [string]$LogFileDir, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [string]$LogFileName = 'WaitJob.log', [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [switch]$OverwriteLog, [Parameter(Mandatory = $false)] [switch]$Output ) Begin { Add-PSSnapin Citrix.* } Process { Function Retryable($err) { return (($err.Exception.Status -ne [System.Net.WebExceptionStatus]::ProtocolError) -Or ($err.Exception.Response.StatusCode -in 502, 503, 504)) } $maxRetryTime = 600 # seconds $maxPollDelay = if ($pollSeconds -gt 60) { $PollSeconds } else { 60 } $errorMessage = $null $artifacts = @{} $jobProfile = {} $telemetry = {} $job = $null # Set parameter 'Verbose' by internal parameter 'VerbosePreference', since the option -Verbose is occupied by powershell cmdlet $Verbose = $VerbosePreference -eq 'Continue' try { LogInit $MyInvocation $LogFileDir $LogFileName $OverwriteLog $Verbose if ($JobId -eq "Job failed to start") { return } if ([string]::IsNullOrWhiteSpace($JobId)) { throw "Must supply a job id" } $parameters = AuthToCitrixCloud $CustomerId $SecureClientId $SecureSecret if ([string]::IsNullOrWhiteSpace($SecureClientId) -Or [string]::IsNullOrWhiteSpace($SecureSecret)) { $SecureClientId = $parameters.ApiKey $SecureSecret = $parameters.SecretKey } $terminated = $false $lastOkTime = Get-Date $pollDelay = $PollSeconds while (-Not $terminated) { try { $job = $null $job = Invoke-CCRestMethod -method 'Get' -deployment $Deployment -serviceRoute "jobs/$JobId" -customerId $CustomerId -secureClientId $SecureClientId $SecureSecret -raw $true LogIt "Job $JobId status: $($job.status) percent done: $($job.overallProgressPercent) $(if ($job.parameters.length) {"parameters $($job.parameters)"})" $lastOkTime = Get-Date $pollDelay = $PollSeconds if ($job.status -in 'notStarted', 'inProgress', 'cancelling') # is the job in a non-terminal state? { Start-Sleep $pollDelay } else { $terminated = $true } } catch { if (!(Retryable $_)) { LogItError "GET jobs/$JobId status error: $_" LogFatal "Fatal error getting the status of job $($JobId): $_" } if (((Get-Date) - $lastOkTime).TotalSeconds -gt $maxRetryTime) { LogItError "GET jobs/$JobId status error: $_" LogFatal "Wait timed out after failing to get the job status for $maxRetryTime minutes" } Start-Sleep $pollDelay $pollDelay = 2 * $pollDelay if ($pollDelay -gt $maxPollDelay) { $pollDelay = $maxPollDelay } } } $jobHash = Convert-Object $job $started = (Get-Date -Date $jobHash.startedAt).ToUniversalTime() $ended = (Get-Date -Date $jobHash.endedAt).ToUniversalTime() $runtime = New-TimeSpan -Start $started -End $ended LogIt "Job $JobId completed in $runtime final status: $($job.status)" if ($jobHash.additionalInfo.warnings.Length -gt 0) { $warnings = "" foreach ($warning in $jobHash.additionalInfo.warnings) { if ($warning.ContainsKey('detail')) { $warnings += $warning.detail + ", " } elseif ($warning.ContainsKey('warning')) { $warnings += $warning.warning + ", " } } LogItWarning "Job warnings: $warnings" } if ($job.status -ne "complete") { $errorMessage = $jobHash.error.detail if ($jobHash.additionalInfo.errors.length -gt 0) { $errorMessage += ": " foreach ($error in $jobHash.additionalInfo.errors) { if ($error.detail) { $message = $error.error + ": " + $error.detail } else { $message = $error.error } $errorMessage += $message + ", " } } LogItError "Job $JobId error: $errorMessage" } LogIt "Completed job $(Convert-HashToString $jobHash) " $false $jobProfile = $jobHash.additionalInfo.profile LogIt "Job profile $(Convert-HashToString $jobProfile))" $false $telemetry = $jobHash.additionalInfo.telemetry LogIt "Job telemetry $(Convert-HashToString $telemetry))" $false $artifacts = $jobHash.additionalInfo.artifacts LogIt "Job artifacts $(Convert-HashToString $artifacts))" $false LogIt "Complete job information including timing and version information written to logfile: $($Global:LogFile)." } finally { # Clear credentials at end of pipeline if ($PSCmdlet.MyInvocation.PipelinePosition -eq $PSCmdlet.MyInvocation.PipelineLength) { Clear-XDCredentials } if ($null -ne $job -and (($PSCmdlet.MyInvocation.PipelinePosition -ne $PSCmdlet.MyInvocation.PipelineLength) -or $Output.IsPresent)) { $OutputData = [PSCustomObject]@{ Status = $job.status Error = $errorMessage Artifacts = $artifacts Profile = $jobProfile Telemetry = $telemetry LogFileDir = $LogFileDir LogFileName = $LogFileName } LogIt "Output $(Convert-ObjectToString $OutputData)" $Verbose Write-Output $OutputData } } } } |