Private/Invoke-AACTerraformCli.ps1
|
function Invoke-AACTerraformCli { <# .SYNOPSIS Runs the terraform CLI once in a folder and returns its exit code and output - Export-AACTerraform -Plan's init, validate, plan and show. .DESCRIPTION Started directly (System.Diagnostics.Process), not through Start-Process: the output is read back, nothing opens a window, and the arguments are passed one by one, so a path with spaces needs no quoting. -Environment adds variables for this run only (TF_IN_AUTOMATION, ARM_SUBSCRIPTION_ID). Past -TimeoutMinutes the process is stopped and ExitCode is -1. Returns @{ ExitCode; Output (standard output); Error (standard error) }. #> [CmdletBinding()] [OutputType([hashtable])] param( [Parameter(Mandatory)] [string] $FilePath, [Parameter(Mandatory)] [string[]] $Argument, [Parameter(Mandatory)] [string] $WorkingDirectory, [System.Collections.IDictionary] $Environment = @{}, [ValidateRange(1, 120)] [int] $TimeoutMinutes = 15 ) $start = [System.Diagnostics.ProcessStartInfo]::new($FilePath) foreach ($item in $Argument) { $start.ArgumentList.Add($item) } $start.WorkingDirectory = $WorkingDirectory $start.UseShellExecute = $false $start.CreateNoWindow = $true $start.RedirectStandardOutput = $true $start.RedirectStandardError = $true foreach ($key in $Environment.Keys) { $start.Environment[[string]$key] = [string]$Environment[$key] } $process = [System.Diagnostics.Process]::Start($start) try { # Both streams read at once: a full stderr buffer would otherwise stall a chatty plan. $output = $process.StandardOutput.ReadToEndAsync() $errorText = $process.StandardError.ReadToEndAsync() if (-not $process.WaitForExit($TimeoutMinutes * 60000)) { $process.Kill($true) return @{ ExitCode = -1; Output = ''; Error = "terraform $($Argument[0]) didn't finish within $TimeoutMinutes minute(s)." } } $process.WaitForExit() @{ ExitCode = $process.ExitCode; Output = $output.Result; Error = $errorText.Result } } finally { $process.Dispose() } } |