mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
e972287c35
* win_exec: refactor PS exec runner * more changes for PSCore compatibility * made some changes based on the recent review * split up module exec scripts for smaller payload * removed C# module support to focus on just error msg improvement * cleaned up c# test classifier code
110 lines
4.5 KiB
PowerShell
110 lines
4.5 KiB
PowerShell
# (c) 2018 Ansible Project
|
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
|
|
param(
|
|
[Parameter(Mandatory=$true)][System.Collections.IDictionary]$Payload
|
|
)
|
|
|
|
# help with debugging errors as we don't have visibility of this running process
|
|
trap {
|
|
$watchdog_path = "$($env:TEMP)\ansible-async-watchdog-error-$(Get-Date -Format "yyyy-MM-ddTHH-mm-ss.ffffZ").txt"
|
|
$error_msg = "Error while running the async exec wrapper`r`n$(Format-AnsibleException -ErrorRecord $_)"
|
|
Set-Content -Path $watchdog_path -Value $error_msg
|
|
break
|
|
}
|
|
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
Write-AnsibleLog "INFO - starting async_watchdog" "async_watchdog"
|
|
|
|
# pop 0th action as entrypoint
|
|
$payload.actions = $payload.actions[1..99]
|
|
|
|
$actions = $Payload.actions
|
|
$entrypoint = $payload.($actions[0])
|
|
$entrypoint = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($entrypoint))
|
|
|
|
$resultfile_path = $payload.async_results_path
|
|
$max_exec_time_sec = $payload.async_timeout_sec
|
|
|
|
Write-AnsibleLog "INFO - deserializing existing result file args at: '$resultfile_path'" "async_watchdog"
|
|
if (-not (Test-Path -Path $resultfile_path)) {
|
|
$msg = "result file at '$resultfile_path' does not exist"
|
|
Write-AnsibleLog "ERROR - $msg" "async_watchdog"
|
|
throw $msg
|
|
}
|
|
$result_json = Get-Content -Path $resultfile_path -Raw
|
|
Write-AnsibleLog "INFO - result file json is: $result_json" "async_watchdog"
|
|
$result = ConvertFrom-AnsibleJson -InputObject $result_json
|
|
|
|
Write-AnsibleLog "INFO - creating async runspace" "async_watchdog"
|
|
$rs = [RunspaceFactory]::CreateRunspace()
|
|
$rs.Open()
|
|
|
|
Write-AnsibleLog "INFO - creating async PowerShell pipeline" "async_watchdog"
|
|
$ps = [PowerShell]::Create()
|
|
$ps.Runspace = $rs
|
|
|
|
# these functions are set in exec_wrapper
|
|
Write-AnsibleLog "INFO - adding global functions to PowerShell pipeline script" "async_watchdog"
|
|
$ps.AddScript($script:common_functions).AddStatement() > $null
|
|
$ps.AddScript($script:wrapper_functions).AddStatement() > $null
|
|
$ps.AddCommand("Set-Variable").AddParameters(@{Name="common_functions"; Value=$script:common_functions; Scope="script"}).AddStatement() > $null
|
|
|
|
Write-AnsibleLog "INFO - adding $($actions[0]) to PowerShell pipeline script" "async_watchdog"
|
|
$ps.AddScript($entrypoint).AddArgument($payload) > $null
|
|
|
|
Write-AnsibleLog "INFO - async job start, calling BeginInvoke()" "async_watchdog"
|
|
$job_async_result = $ps.BeginInvoke()
|
|
|
|
Write-AnsibleLog "INFO - waiting '$max_exec_time_sec' seconds for async job to complete" "async_watchdog"
|
|
$job_async_result.AsyncWaitHandle.WaitOne($max_exec_time_sec * 1000) > $null
|
|
$result.finished = 1
|
|
|
|
if ($job_async_result.IsCompleted) {
|
|
Write-AnsibleLog "INFO - async job completed, calling EndInvoke()" "async_watchdog"
|
|
|
|
$job_output = $ps.EndInvoke($job_async_result)
|
|
$job_error = $ps.Streams.Error
|
|
|
|
Write-AnsibleLog "INFO - raw module stdout:`r`n$($job_output | Out-String)" "async_watchdog"
|
|
if ($job_error) {
|
|
Write-AnsibleLog "WARN - raw module stderr:`r`n$($job_error | Out-String)" "async_watchdog"
|
|
}
|
|
|
|
# write success/output/error to result object
|
|
# TODO: cleanse leading/trailing junk
|
|
try {
|
|
Write-AnsibleLog "INFO - deserializing Ansible stdout" "async_watchdog"
|
|
$module_result = ConvertFrom-AnsibleJson -InputObject $job_output
|
|
# TODO: check for conflicting keys
|
|
$result = $result + $module_result
|
|
} catch {
|
|
$result.failed = $true
|
|
$result.msg = "failed to parse module output: $($_.Exception.Message)"
|
|
# return output back to Ansible to help with debugging errors
|
|
$result.stdout = $job_output | Out-String
|
|
$result.stderr = $job_error | Out-String
|
|
}
|
|
|
|
$result_json = ConvertTo-Json -InputObject $result -Depth 99 -Compress
|
|
Set-Content -Path $resultfile_path -Value $result_json
|
|
|
|
Write-AnsibleLog "INFO - wrote output to $resultfile_path" "async_watchdog"
|
|
} else {
|
|
Write-AnsibleLog "ERROR - reached timeout on async job, stopping job" "async_watchdog"
|
|
$ps.BeginStop($null, $null) > $null # best effort stop
|
|
|
|
# write timeout to result object
|
|
$result.failed = $true
|
|
$result.msg = "timed out waiting for module completion"
|
|
$result_json = ConvertTo-Json -InputObject $result -Depth 99 -Compress
|
|
Set-Content -Path $resultfile_path -Value $result_json
|
|
|
|
Write-AnsibleLog "INFO - wrote timeout to '$resultfile_path'" "async_watchdog"
|
|
}
|
|
|
|
# in the case of a hung pipeline, this will cause the process to stay alive until it's un-hung...
|
|
#$rs.Close() | Out-Null
|
|
|
|
Write-AnsibleLog "INFO - ending async_watchdog" "async_watchdog"
|