lib/TaskActions.ps1
function Start-TMTaskAction { param ( [Parameter(Mandatory = $false, Position = 0)] [String]$TMSession = "Default", [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [Alias('Id')] [Int]$TaskId, [Parameter(Mandatory = $false)] [Switch]$Force, [Parameter(Mandatory = $false)] [Bool]$Api = $false ) begin { # Get the session configuration Write-Verbose "Checking for cached TMSession" $TMSessionConfig = $global:TMSessions[$TMSession] Write-Debug "TMSessionConfig:" Write-Debug ($TMSessionConfig | ConvertTo-Json -Depth 5) if (-not $TMSessionConfig) { throw "TMSession '$TMSession' not found. Use New-TMSession command before using features." } } process { if ($TMSessionConfig.TMRestSession -and $Api) { Write-Verbose "Using REST API endpoint" Write-Verbose "Forming web request parameters" $RestSplat = @{ Uri = "https://$($TMSessionConfig.TMServer)/tdstm/api/task/$($TaskId)/recordRemoteActionStarted?publicKey=$($TMSessionConfig.AuthTokens.PublicKey -replace "`n", '\n')" Method = 'POST' WebSession = $TMSessionConfig.TMRestSession SkipHttpErrorCheck = $true StatusCodeVariable = 'StatusCode' } Write-Debug "Web Request Parameters:" Write-Debug ($RestSplat | ConvertTo-Json -Depth 10) Write-Verbose "Invoking REST method" try { $Response = Invoke-RestMethod @RestSplat if ($StatusCode -notin 200, 204) { if ($Force -and (${Response}?[0] -eq 'The action has already been invoked')) { Write-Verbose "The action has already been invoked. Resetting action state." Reset-TMTaskAction -TMSession $TMSession -TaskId $TaskId $Response = Invoke-RestMethod @RestSplat } elseif ($Response) { throw $Response } else { throw "Status code $StatusCode does not indicate success" } } Write-Debug "Response:" Write-Debug ($Response | ConvertTo-Json -Depth 10) $Response # [TMActionRequest]::new($Response) } catch { throw "Error while starting Task Action: $($_.Exception.Message)" } } else { Write-Verbose "Using web service endpoint" Write-Verbose "Forming web request parameters" $WebRequestSplat = @{ Uri = "https://$($TMSessionConfig.TMServer)/tdstm/ws/task/$($TaskId)/recordRemoteActionStarted" Method = 'POST' WebSession = $TMSessionConfig.TMWebSession Body = (@{ publicKey = $TMSessionConfig.AuthTokens.PublicKey } | ConvertTo-Json -Compress) } Write-Debug "Web Request Parameters:" Write-Debug ($WebRequestSplat | ConvertTo-Json -Depth 10) Write-Verbose "Invoking web request" try { $Response = Invoke-WebRequest @WebRequestSplat Write-Debug "Response Content: $($Response.Content)" if ($Response.StatusCode -in 200, 204) { ## Response should be JSON, but might not be, with an error try { $ResponseContent = $Response.Content | ConvertFrom-Json } catch { Write-Debug "Output is not JSON: $($Response.Content)" } # Check for errors in the response $ResponseErrors = if ($Response.Headers.Keys -contains 'X-TM-Error-Message') { $Response.Headers.'X-TM-Error-Message' } elseif (${ResponseContent}?.status -eq 'error') { ${ResponseContent}.errors } else { $null } # Deal with error(s) if possible if ($ResponseErrors) { switch ($ResponseErrors) { { $_ -contains 'The task must be in the Ready or Started state in order to invoke action' -or $_ -eq 'The task must be in the Ready or Started state in order to invoke action' } { ## This Status message is handled by the TMBrokerSubject class itself. bypass throwing any specific message ## TODO: Lookup the current task state so this can report who, when and where the task was executed return } { $_ -contains 'The action has already been invoked' -or $_ -eq 'The action has already been invoked' } { if ($Force) { Write-Verbose "The action has already been invoked. Resetting action state." Reset-TMTaskAction -TMSession $TMSession -TaskId $TaskId Start-TMTaskAction -TMSession $TMSession -TaskId $TaskId -Force:$Force -Api $Api } else { Write-Verbose "The action has already been invoked. -Force switch was not passed." } return } default { Write-Host "Subject Task could not be invoked: $ResponseErrors" -ForegroundColor Magenta return } } } else { ${ResponseContent}?.actionRequest } } else { throw "Status code $($Response.StatusCode) does not indicate success" } } catch { throw "Error while starting Task Action: $($_.Exception.Message)" } } } } function Stop-TMTaskAction { param ( [Parameter(Mandatory = $false, Position = 0)] [String]$TMSession = "Default", [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [Alias('Id')] [Int]$TaskId, [Parameter(Mandatory = $false)] [Nullable[Int]]$ProjectId, [Parameter(Mandatory = $false)] [String]$Message, [Parameter(Mandatory = $false)] [String]$StdOut, [Parameter(Mandatory = $false)] [String]$StdErr, [Parameter(Mandatory = $false)] [Switch]$ReportError ) begin { # Get the session configuration Write-Verbose "Checking for cached TMSession" $TMSessionConfig = $global:TMSessions[$TMSession] Write-Debug "TMSessionConfig:" Write-Debug ($TMSessionConfig | ConvertTo-Json -Depth 5) if (-not $TMSessionConfig) { throw "TMSession '$TMSession' not found. Use New-TMSession command before using features." } # Make sure we have a bearer token for the REST endpoint Write-Verbose "Checking for TMRestSession with bearer token" if (-not $TMSessionConfig.TMRestSession) { throw "TMSession '$TMSession' is not logged into the TransitionManager API. Use New-TMSession -Api `$true command to connect to a compatible server." } # Use the TM session if a project id is not provided $ProjectId ??= $TMSessionConfig.UserContext.Project.id } process { Write-Verbose "Using REST API endpoint" Write-Verbose "Forming web request parameters" $Body = @{ project = $ProjectId } if (-not [String]::IsNullOrWhiteSpace($StdOut)) { $Body.stdout = $StdOut } if (-not [String]::IsNullOrWhiteSpace($StdErr)) { $Body.stderr = $StdErr } if (-not [String]::IsNullOrWhiteSpace($Message)) { $Body.message = $Message } $RestSplat = @{ Uri = "https://$($TMSessionConfig.TMServer)/tdstm/api/task/$($TaskId)/$($ReportError.IsPresent ? 'actionError' : 'actionDone')" Method = 'POST' Body = ($Body | ConvertTo-Json) WebSession = $TMSessionConfig.TMRestSession } Write-Debug "Web Request Parameters:" Write-Debug ($RestSplat | ConvertTo-Json -Depth 10) Write-Verbose "Invoking REST method" try { $Response = Invoke-RestMethod @RestSplat Write-Debug "Response:" Write-Debug ($Response | ConvertTo-Json -Depth 10) } catch { throw "Error while stopping Task Action: $($_.Exception.Message)" } } } function Reset-TMTaskAction { param ( [Parameter(Mandatory = $false, Position = 0)] [String]$TMSession = "Default", [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [Alias('Id')] [Int]$TaskId ) begin { # Get the session configuration Write-Verbose "Checking for cached TMSession" $TMSessionConfig = $global:TMSessions[$TMSession] Write-Debug "TMSessionConfig:" Write-Debug ($TMSessionConfig | ConvertTo-Json -Depth 5) if (-not $TMSessionConfig) { throw "TMSession '$TMSession' not found. Use New-TMSession command before using features." } } process { Write-Verbose "Forming web request parameters" $WebRequestSplat = @{ Uri = "https://$($TMSessionConfig.TMServer)/tdstm/ws/task/$($TaskId)/resetAction" Method = 'POST' WebSession = $TMSessionConfig.TMWebSession } Write-Debug "Web Request Parameters:" Write-Debug ($WebRequestSplat | ConvertTo-Json -Depth 10) Write-Verbose "Invoking web request" try { $Response = Invoke-WebRequest @WebRequestSplat Write-Debug "Response Content:" Write-Debug ($Response.Content | ConvertTo-Json -Depth 10) if ($Response.StatusCode -notin 200, 204) { throw "Status code $($Response.StatusCode) does not indicate success" } } catch { throw "Error while resetting task action: $($_.Exception.Message)" } } } |