1151 lines
42 KiB
PowerShell
1151 lines
42 KiB
PowerShell
param(
|
||
[string]$ConfigPath = (Join-Path $PSScriptRoot 'config.txt'),
|
||
[string]$Action = '',
|
||
[string]$Ip = '',
|
||
[string]$HashCode = '',
|
||
[string]$RollbackIp = '',
|
||
[switch]$RollbackStopFirst,
|
||
[switch]$Help
|
||
)
|
||
|
||
# PAM 部署主脚本(PowerShell 实现)。
|
||
Set-StrictMode -Version Latest
|
||
$ErrorActionPreference = 'Stop'
|
||
|
||
function Show-DeployUsage {
|
||
@'
|
||
Usage:
|
||
powershell -File .\deploy.ps1 [-ConfigPath .\config.txt]
|
||
powershell -File .\deploy.ps1 -Action <Name> [-ConfigPath .\config.txt] [-Ip 192.168.1.10] [-HashCode xxxxx] [-RollbackStopFirst]
|
||
powershell -File .\deploy.ps1 [-ConfigPath .\config.txt] -RollbackIp 192.168.1.10 [-RollbackStopFirst]
|
||
|
||
Notes:
|
||
- deploy.bat is only a wrapper for this script.
|
||
- The wrapper avoids cmd.exe delayed-expansion issues with CLIENT_SECRET values
|
||
containing exclamation marks.
|
||
'@ | Write-Host
|
||
}
|
||
|
||
function Write-Info([string]$Message) { Write-Host "[INFO] $Message" }
|
||
function Write-WarnLog([string]$Message) { Write-Host "[WARN] $Message" }
|
||
function Write-ErrLog([string]$Message) { Write-Host "[ERROR] $Message" }
|
||
$script:ActiveConfigPath = $ConfigPath
|
||
$script:DownloadProgressState = [ordered]@{
|
||
Status = ''
|
||
Success = ''
|
||
Step = ''
|
||
Msg = ''
|
||
Message = ''
|
||
RateOfProgress = ''
|
||
RawResponse = ''
|
||
}
|
||
|
||
function Write-ResultLine([string]$Key, [AllowEmptyString()][string]$Value) {
|
||
if ($null -eq $Value) {
|
||
$Value = ''
|
||
}
|
||
$normalized = $Value.Replace("`r", ' ').Replace("`n", ' ')
|
||
Write-Host ("{0}={1}" -f $Key, $normalized)
|
||
}
|
||
|
||
function Require-IpArgument([string]$TargetIp) {
|
||
if (-not $TargetIp) {
|
||
throw 'This action requires -Ip.'
|
||
}
|
||
}
|
||
|
||
function Require-HashCodeArgument([string]$PublishHashCode) {
|
||
if (-not $PublishHashCode) {
|
||
throw 'This action requires -HashCode.'
|
||
}
|
||
}
|
||
|
||
function Write-OnlineIpsResult([string[]]$Ips) {
|
||
Write-ResultLine -Key 'ACTION' -Value 'get-online-ips'
|
||
Write-ResultLine -Key 'COUNT' -Value ([string]$Ips.Count)
|
||
foreach ($entry in $Ips) {
|
||
Write-ResultLine -Key 'IP' -Value $entry
|
||
}
|
||
}
|
||
|
||
function Write-DownloadProgressResult([string]$ActionName = 'poll-download-progress') {
|
||
Write-ResultLine -Key 'ACTION' -Value $ActionName
|
||
Write-ResultLine -Key 'STEP' -Value ([string]$script:DownloadProgressState.Step)
|
||
Write-ResultLine -Key 'MSG' -Value ([string]$script:DownloadProgressState.Msg)
|
||
Write-ResultLine -Key 'RATE_OF_PROGRESS' -Value ([string]$script:DownloadProgressState.RateOfProgress)
|
||
Write-ResultLine -Key 'STATUS' -Value ([string]$script:DownloadProgressState.Status)
|
||
Write-ResultLine -Key 'SUCCESS' -Value ([string]$script:DownloadProgressState.Success)
|
||
Write-ResultLine -Key 'MESSAGE' -Value ([string]$script:DownloadProgressState.Message)
|
||
}
|
||
|
||
function Write-FlowStart([string]$Name, [string]$Detail = '') {
|
||
if ($Detail) {
|
||
Write-Info "[FLOW][START] $Name | $Detail"
|
||
} else {
|
||
Write-Info "[FLOW][START] $Name"
|
||
}
|
||
}
|
||
|
||
function Write-FlowDone([string]$Name, [string]$Detail = '') {
|
||
if ($Detail) {
|
||
Write-Info "[FLOW][DONE] $Name | $Detail"
|
||
} else {
|
||
Write-Info "[FLOW][DONE] $Name"
|
||
}
|
||
}
|
||
|
||
function Write-FlowFail([string]$Name, [string]$Detail = '') {
|
||
if ($Detail) {
|
||
Write-ErrLog "[FLOW][FAIL] $Name | $Detail"
|
||
} else {
|
||
Write-ErrLog "[FLOW][FAIL] $Name"
|
||
}
|
||
}
|
||
|
||
function Invoke-FlowStep {
|
||
param(
|
||
[string]$Name,
|
||
[scriptblock]$Action,
|
||
[string]$Detail = ''
|
||
)
|
||
|
||
Write-FlowStart -Name $Name -Detail $Detail
|
||
try {
|
||
$result = & $Action
|
||
Write-FlowDone -Name $Name
|
||
return $result
|
||
} catch {
|
||
Write-FlowFail -Name $Name -Detail $_.Exception.Message
|
||
throw
|
||
}
|
||
}
|
||
|
||
function Get-ManualRollbackCommand {
|
||
param(
|
||
[string]$Ip,
|
||
[bool]$StopFirst
|
||
)
|
||
|
||
$command = "powershell -File .\deploy.ps1 -ConfigPath `"$script:ActiveConfigPath`" -RollbackIp `"$Ip`""
|
||
if ($StopFirst) {
|
||
$command += ' -RollbackStopFirst'
|
||
}
|
||
|
||
return $command
|
||
}
|
||
|
||
function Get-PendingRollbackStatus {
|
||
param(
|
||
[string]$Ip,
|
||
[string]$Stage,
|
||
[bool]$StopFirst,
|
||
[string]$Reason
|
||
)
|
||
|
||
$status = "PENDING_AGENT_CONFIRMATION(stopFirst=$($StopFirst.ToString().ToLowerInvariant()))"
|
||
$command = Get-ManualRollbackCommand -Ip $Ip -StopFirst $StopFirst
|
||
Write-WarnLog "检测到需要回滚: ip=$Ip stage=$Stage reason=$Reason stopFirst=$StopFirst"
|
||
Write-WarnLog "当前脚本不会自动执行回滚。请由 Agent 与用户确认后,再执行: $command"
|
||
return $status
|
||
}
|
||
|
||
function Convert-ResponseContent {
|
||
param([AllowNull()][string]$Content)
|
||
|
||
if ([string]::IsNullOrWhiteSpace($Content)) {
|
||
return $null
|
||
}
|
||
|
||
try {
|
||
if ($PSVersionTable.PSVersion.Major -ge 6) {
|
||
return $Content | ConvertFrom-Json -Depth 100
|
||
}
|
||
|
||
return $Content | ConvertFrom-Json
|
||
} catch {
|
||
return $Content
|
||
}
|
||
}
|
||
|
||
function Get-ErrorBody {
|
||
param([System.Management.Automation.ErrorRecord]$ErrorRecord)
|
||
|
||
try {
|
||
$response = $ErrorRecord.Exception.Response
|
||
if ($null -eq $response) {
|
||
return $ErrorRecord.Exception.Message
|
||
}
|
||
|
||
$stream = $response.GetResponseStream()
|
||
if ($null -eq $stream) {
|
||
return $ErrorRecord.Exception.Message
|
||
}
|
||
|
||
$reader = New-Object System.IO.StreamReader($stream)
|
||
try {
|
||
return $reader.ReadToEnd()
|
||
} finally {
|
||
$reader.Dispose()
|
||
}
|
||
} catch {
|
||
return $ErrorRecord.Exception.Message
|
||
}
|
||
}
|
||
|
||
function Get-ResponseValue {
|
||
param(
|
||
$Response,
|
||
[string[]]$Candidates
|
||
)
|
||
|
||
foreach ($candidate in $Candidates) {
|
||
$current = $Response
|
||
foreach ($segment in ($candidate -split '\.')) {
|
||
if ($null -eq $current) {
|
||
break
|
||
}
|
||
|
||
if ($current -is [string]) {
|
||
$current = $null
|
||
break
|
||
}
|
||
|
||
if ($current -is [System.Collections.IDictionary]) {
|
||
if ($current.Contains($segment)) {
|
||
$current = $current[$segment]
|
||
} else {
|
||
$current = $null
|
||
break
|
||
}
|
||
} elseif ($current.PSObject.Properties.Name -contains $segment) {
|
||
$current = $current.$segment
|
||
} else {
|
||
$current = $null
|
||
break
|
||
}
|
||
}
|
||
|
||
if ($null -ne $current -and -not [string]::IsNullOrWhiteSpace([string]$current)) {
|
||
return [string]$current
|
||
}
|
||
}
|
||
|
||
return $null
|
||
}
|
||
|
||
function Get-PamConfig {
|
||
param([string]$Path)
|
||
|
||
$config = [ordered]@{}
|
||
|
||
if (Test-Path -LiteralPath $Path) {
|
||
foreach ($rawLine in Get-Content -LiteralPath $Path -Encoding UTF8) {
|
||
$line = $rawLine.TrimEnd("`r")
|
||
if ($line -match '^\s*$' -or $line -match '^\s*[#;]') {
|
||
continue
|
||
}
|
||
|
||
$index = $line.IndexOf('=')
|
||
if ($index -lt 1) {
|
||
continue
|
||
}
|
||
|
||
$key = $line.Substring(0, $index).Trim()
|
||
$value = $line.Substring($index + 1).Trim()
|
||
if ($value -match '^(.*?\S)\s+[;#].*$') {
|
||
$value = $Matches[1]
|
||
}
|
||
|
||
switch ($key) {
|
||
'HOME_BASE_URL' { $config[$key] = $value }
|
||
'CLIENT_ID' { $config[$key] = $value }
|
||
'CLIENT_SECRET' { $config[$key] = $value }
|
||
'AIRPORT_CODE' { $config[$key] = $value }
|
||
'APP_NAME' { $config[$key] = $value }
|
||
'MODULE_NAME' { $config[$key] = $value }
|
||
'VERSION_NUMBER' { $config[$key] = $value }
|
||
'ZIP_FILE_PATH' { $config[$key] = $value }
|
||
'ACTION_TYPE' { $config[$key] = $value }
|
||
'TIMEOUT' { $config[$key] = $value }
|
||
'LOG_NAME' { $config[$key] = $value }
|
||
}
|
||
}
|
||
} else {
|
||
Write-WarnLog "Config file not found: $Path. Defaults will be used."
|
||
}
|
||
|
||
$defaults = [ordered]@{
|
||
HOME_BASE_URL = 'https://pam.home.com'
|
||
CLIENT_ID = 'your_client_id'
|
||
CLIENT_SECRET = 'your_client_secret'
|
||
AIRPORT_CODE = 'HET'
|
||
APP_NAME = 'PAM'
|
||
MODULE_NAME = 'Node'
|
||
VERSION_NUMBER = '2.0.5'
|
||
ZIP_FILE_PATH = 'C:\path\to\pam-2.0.5.zip'
|
||
ACTION_TYPE = 'FULL'
|
||
TIMEOUT = '120'
|
||
LOG_NAME = 'app.log'
|
||
}
|
||
|
||
foreach ($name in $defaults.Keys) {
|
||
if (-not $config.Contains($name) -or [string]::IsNullOrWhiteSpace([string]$config[$name])) {
|
||
$config[$name] = $defaults[$name]
|
||
}
|
||
}
|
||
|
||
return [pscustomobject]$config
|
||
}
|
||
|
||
function Join-RequestPairs {
|
||
param([System.Collections.IDictionary]$Values)
|
||
|
||
$pairs = foreach ($key in $Values.Keys) {
|
||
$encodedValue = [System.Uri]::EscapeDataString([string]$Values[$key])
|
||
'{0}={1}' -f $key, $encodedValue
|
||
}
|
||
|
||
return ($pairs -join '&')
|
||
}
|
||
|
||
function Test-ZipFile {
|
||
param($Config)
|
||
|
||
if (-not (Test-Path -LiteralPath $Config.ZIP_FILE_PATH)) {
|
||
throw "Package file not found: $($Config.ZIP_FILE_PATH)"
|
||
}
|
||
}
|
||
|
||
function Invoke-PamWebRequest {
|
||
param(
|
||
[ValidateSet('GET', 'POST', 'PUT')]
|
||
[string]$Method,
|
||
[string]$Url,
|
||
[string]$Token,
|
||
[hashtable]$Headers = @{},
|
||
[AllowNull()]$Body = $null,
|
||
[string]$ContentType = '',
|
||
[string]$OutFile = ''
|
||
)
|
||
|
||
$allHeaders = @{}
|
||
if ($Token) {
|
||
$allHeaders['Authorization'] = "Bearer $Token"
|
||
}
|
||
foreach ($key in $Headers.Keys) {
|
||
$allHeaders[$key] = $Headers[$key]
|
||
}
|
||
|
||
$params = @{
|
||
Uri = $Url
|
||
Method = $Method
|
||
Headers = $allHeaders
|
||
ErrorAction = 'Stop'
|
||
}
|
||
|
||
if ($PSVersionTable.PSVersion.Major -lt 6) {
|
||
$params['UseBasicParsing'] = $true
|
||
}
|
||
|
||
if ($PSBoundParameters.ContainsKey('Body') -and $null -ne $Body -and "$Body" -ne '') {
|
||
$params['Body'] = $Body
|
||
}
|
||
|
||
if ($ContentType) {
|
||
$params['ContentType'] = $ContentType
|
||
}
|
||
|
||
if ($OutFile) {
|
||
$params['OutFile'] = $OutFile
|
||
}
|
||
|
||
try {
|
||
$response = Invoke-WebRequest @params
|
||
if ($OutFile) {
|
||
return $OutFile
|
||
}
|
||
return Convert-ResponseContent $response.Content
|
||
} catch {
|
||
$body = Get-ErrorBody $_
|
||
throw "Request failed [$Method] $Url`n$body"
|
||
}
|
||
}
|
||
|
||
function Invoke-PamMultipartUpload {
|
||
param(
|
||
[string]$Url,
|
||
[string]$Token,
|
||
[string]$FilePath,
|
||
[hashtable]$Fields
|
||
)
|
||
|
||
Add-Type -AssemblyName System.Net.Http
|
||
|
||
$client = [System.Net.Http.HttpClient]::new()
|
||
try {
|
||
$client.DefaultRequestHeaders.Authorization =
|
||
[System.Net.Http.Headers.AuthenticationHeaderValue]::new('Bearer', $Token)
|
||
|
||
$content = [System.Net.Http.MultipartFormDataContent]::new()
|
||
foreach ($entry in $Fields.GetEnumerator()) {
|
||
$stringContent = [System.Net.Http.StringContent]::new([string]$entry.Value, [System.Text.Encoding]::UTF8)
|
||
$content.Add($stringContent, $entry.Key)
|
||
}
|
||
|
||
$stream = [System.IO.File]::OpenRead($FilePath)
|
||
try {
|
||
$fileContent = [System.Net.Http.StreamContent]::new($stream)
|
||
$fileContent.Headers.ContentType =
|
||
[System.Net.Http.Headers.MediaTypeHeaderValue]::Parse('application/octet-stream')
|
||
$content.Add($fileContent, 'file', [System.IO.Path]::GetFileName($FilePath))
|
||
|
||
$response = $client.PostAsync($Url, $content).GetAwaiter().GetResult()
|
||
$body = $response.Content.ReadAsStringAsync().GetAwaiter().GetResult()
|
||
if (-not $response.IsSuccessStatusCode) {
|
||
throw "Upload failed [HTTP $([int]$response.StatusCode)]`n$body"
|
||
}
|
||
|
||
return Convert-ResponseContent $body
|
||
} finally {
|
||
$stream.Dispose()
|
||
}
|
||
} finally {
|
||
$client.Dispose()
|
||
}
|
||
}
|
||
|
||
function Get-Token {
|
||
param($Config)
|
||
|
||
Write-Info 'Getting token...'
|
||
$body = Join-RequestPairs ([ordered]@{
|
||
grant_type = 'client_credentials'
|
||
client_id = $Config.CLIENT_ID
|
||
client_secret = $Config.CLIENT_SECRET
|
||
})
|
||
$response = Invoke-PamWebRequest -Method POST -Url "$($Config.HOME_BASE_URL)/oauth/token" -Token '' -Body $body -ContentType 'application/x-www-form-urlencoded'
|
||
$token = Get-ResponseValue -Response $response -Candidates @('access_token')
|
||
if (-not $token) {
|
||
throw "Invalid token response: $response"
|
||
}
|
||
return $token
|
||
}
|
||
|
||
function New-VersionRecord {
|
||
param($Config, [string]$Token)
|
||
|
||
Write-Info 'Step 2.1: create version record'
|
||
$body = Join-RequestPairs ([ordered]@{
|
||
versionNumber = $Config.VERSION_NUMBER
|
||
applicationName = $Config.APP_NAME
|
||
moduleName = $Config.MODULE_NAME
|
||
description = 'Auto Deploy'
|
||
})
|
||
[void](Invoke-PamWebRequest -Method POST -Url "$($Config.HOME_BASE_URL)/api/version/upgrade" -Token $Token -Body $body -ContentType 'application/x-www-form-urlencoded')
|
||
}
|
||
|
||
function Upload-Package {
|
||
param($Config, [string]$Token)
|
||
|
||
Write-Info 'Step 2.2: upload package'
|
||
$response = Invoke-PamMultipartUpload -Url "$($Config.HOME_BASE_URL)/api/version/upgrade/upload" -Token $Token -FilePath $Config.ZIP_FILE_PATH -Fields @{
|
||
applicationName = $Config.APP_NAME
|
||
moduleName = $Config.MODULE_NAME
|
||
versionNumber = $Config.VERSION_NUMBER
|
||
}
|
||
|
||
$hashCode = Get-ResponseValue -Response $response -Candidates @('hashCode', 'data.hashCode')
|
||
if (-not $hashCode -and $response -is [string]) {
|
||
$hashCode = $response.Trim()
|
||
}
|
||
if (-not $hashCode) {
|
||
throw "Unable to parse hashCode from upload response: $response"
|
||
}
|
||
|
||
return $hashCode
|
||
}
|
||
|
||
function Publish-Version {
|
||
param($Config, [string]$Token, [string]$HashCode)
|
||
|
||
Write-Info 'Step 2.3: publish version'
|
||
$payload = @{
|
||
airportCodesWhite = @($Config.AIRPORT_CODE)
|
||
hashCode = $HashCode
|
||
state = 'RELEASE'
|
||
} | ConvertTo-Json -Depth 5
|
||
|
||
$query = Join-RequestPairs ([ordered]@{
|
||
versionNumber = $Config.VERSION_NUMBER
|
||
applicationName = $Config.APP_NAME
|
||
moduleName = $Config.MODULE_NAME
|
||
})
|
||
|
||
[void](Invoke-PamWebRequest -Method PUT -Url "$($Config.HOME_BASE_URL)/api/version/upgrade/profile?$query" -Token $Token -Body $payload -ContentType 'application/json')
|
||
}
|
||
|
||
function Get-NodeUrl {
|
||
param($Config, [string]$Token)
|
||
|
||
Write-Info 'Step 3.1: resolve node url'
|
||
$response = Invoke-PamWebRequest -Method GET -Url "$($Config.HOME_BASE_URL)/api/mcp/airport/target-node?airportCode=$($Config.AIRPORT_CODE)" -Token $Token
|
||
|
||
if ($response -is [System.Collections.IDictionary]) {
|
||
return [string]($response.Keys | Select-Object -First 1)
|
||
}
|
||
|
||
$propertyNames = @($response.PSObject.Properties.Name)
|
||
if ($propertyNames.Count -gt 0) {
|
||
return [string]$propertyNames[0]
|
||
}
|
||
|
||
throw "Unable to resolve node url: $response"
|
||
}
|
||
|
||
function Get-OnlineIps {
|
||
param($Config, [string]$Token, [string]$NodeUrl)
|
||
|
||
Write-Info 'Step 3.2: query online IP list'
|
||
$query = Join-RequestPairs ([ordered]@{
|
||
applicationName = $Config.APP_NAME
|
||
moduleName = $Config.MODULE_NAME
|
||
airportCode = $Config.AIRPORT_CODE
|
||
})
|
||
|
||
$response = Invoke-PamWebRequest -Method GET -Url "$($Config.HOME_BASE_URL)/node-proxy/$($Config.AIRPORT_CODE)/api/mcp/version/upgrade/ips?$query" -Token $Token -Headers @{
|
||
'Target-Node' = $NodeUrl
|
||
}
|
||
|
||
$ips = @()
|
||
if ($response -is [System.Array]) {
|
||
$ips = @($response | ForEach-Object { [string]$_ } | Where-Object { $_ })
|
||
} elseif ($response -is [System.Collections.IEnumerable] -and -not ($response -is [string])) {
|
||
$ips = @($response | ForEach-Object { [string]$_ } | Where-Object { $_ })
|
||
}
|
||
|
||
if ($ips.Count -eq 0) {
|
||
throw "No online workstation matched the module. Raw response: $response"
|
||
}
|
||
|
||
return $ips
|
||
}
|
||
|
||
function Wait-DownloadProgress {
|
||
param($Config, [string]$Token, [string]$NodeUrl)
|
||
|
||
$query = Join-RequestPairs ([ordered]@{
|
||
applicationName = $Config.APP_NAME
|
||
moduleName = $Config.MODULE_NAME
|
||
airportCode = $Config.AIRPORT_CODE
|
||
versionNumber = $Config.VERSION_NUMBER
|
||
})
|
||
$progressUrl = "$($Config.HOME_BASE_URL)/node-proxy/$($Config.AIRPORT_CODE)/api/mcp/version/upgrade/download-cloud/progress?$query"
|
||
$script:DownloadProgressState = [ordered]@{
|
||
Status = ''
|
||
Success = ''
|
||
Step = ''
|
||
Msg = ''
|
||
Message = ''
|
||
RateOfProgress = ''
|
||
RawResponse = ''
|
||
}
|
||
|
||
for ($attempt = 0; $attempt -lt 60; $attempt++) {
|
||
$response = Invoke-PamWebRequest -Method GET -Url $progressUrl -Token $Token -Headers @{
|
||
'Target-Node' = $NodeUrl
|
||
}
|
||
|
||
$status = Get-ResponseValue -Response $response -Candidates @('status')
|
||
$successFlag = Get-ResponseValue -Response $response -Candidates @('success')
|
||
$step = Get-ResponseValue -Response $response -Candidates @('step')
|
||
$msg = Get-ResponseValue -Response $response -Candidates @('msg')
|
||
$progressValue = Get-ResponseValue -Response $response -Candidates @('rateOfProgress', 'progress', 'percent', 'data.rateOfProgress', 'data.progress', 'data.percent')
|
||
$message = Get-ResponseValue -Response $response -Candidates @('message')
|
||
if (-not $message) { $message = $msg }
|
||
$script:DownloadProgressState = [ordered]@{
|
||
Status = [string]$status
|
||
Success = [string]$successFlag
|
||
Step = [string]$step
|
||
Msg = [string]$msg
|
||
Message = [string]$message
|
||
RateOfProgress = [string]$progressValue
|
||
RawResponse = [string]$response
|
||
}
|
||
|
||
$progressParts = [System.Collections.Generic.List[string]]::new()
|
||
if ($msg) { $progressParts.Add("msg=$msg") }
|
||
if ($step) { $progressParts.Add("step=$step") }
|
||
if ($progressValue) { $progressParts.Add("rateOfProgress=$progressValue") }
|
||
if ($status) { $progressParts.Add("status=$status") }
|
||
if ($successFlag) { $progressParts.Add("success=$successFlag") }
|
||
if ($message -and $message -ne $msg) { $progressParts.Add("message=$message") }
|
||
|
||
if ($progressParts.Count -gt 0) {
|
||
Write-Info ("Step 3.3b: async download progress -> {0}" -f ($progressParts -join ', '))
|
||
} else {
|
||
Write-Info ("Step 3.3b: async download progress polling... ({0}/60)" -f ($attempt + 1))
|
||
}
|
||
|
||
if ($step -eq 'DONE' -or $status -eq 'completed' -or $successFlag -eq 'true' -or (($msg -eq 'success') -and ($progressValue -eq '100'))) {
|
||
return
|
||
}
|
||
|
||
if ((@($step, $message, $msg) -join ' ') -match '(?i)fail|error') {
|
||
if (-not $message) { $message = $step }
|
||
if (-not $message) { $message = $msg }
|
||
throw "Node download failed: $message"
|
||
}
|
||
|
||
Start-Sleep -Seconds 2
|
||
}
|
||
|
||
throw 'Node download timed out.'
|
||
}
|
||
|
||
function Create-DownloadTask {
|
||
param($Config, [string]$Token, [string]$NodeUrl)
|
||
|
||
Write-Info 'Step 3.3: download package to node'
|
||
$query = Join-RequestPairs ([ordered]@{
|
||
versionNumber = $Config.VERSION_NUMBER
|
||
applicationName = $Config.APP_NAME
|
||
moduleName = $Config.MODULE_NAME
|
||
timeOut = '0'
|
||
})
|
||
|
||
[void](Invoke-PamWebRequest -Method GET -Url "$($Config.HOME_BASE_URL)/node-proxy/$($Config.AIRPORT_CODE)/api/mcp/version/upgrade/download-cloud?$query" -Token $Token -Headers @{
|
||
'Target-Node' = $NodeUrl
|
||
'airport-code' = $Config.AIRPORT_CODE
|
||
})
|
||
}
|
||
|
||
function Download-CloudToNode {
|
||
param($Config, [string]$Token, [string]$NodeUrl)
|
||
|
||
Create-DownloadTask -Config $Config -Token $Token -NodeUrl $NodeUrl
|
||
Wait-DownloadProgress -Config $Config -Token $Token -NodeUrl $NodeUrl
|
||
}
|
||
|
||
function Invoke-UpgradeRequest {
|
||
param($Config, [string]$Token, [string]$NodeUrl, [string]$Ip)
|
||
|
||
$query = Join-RequestPairs ([ordered]@{
|
||
airportCode = $Config.AIRPORT_CODE
|
||
targetIp = $Ip
|
||
applicationName = $Config.APP_NAME
|
||
moduleName = $Config.MODULE_NAME
|
||
versionNumber = $Config.VERSION_NUMBER
|
||
action = $Config.ACTION_TYPE
|
||
autoStart = 'false'
|
||
timeOut = $Config.TIMEOUT
|
||
})
|
||
|
||
Invoke-PamWebRequest -Method POST -Url "$($Config.HOME_BASE_URL)/node-proxy/$($Config.AIRPORT_CODE)/api/mcp/version/upgrade?$query" -Token $Token -Headers @{
|
||
'Target-Node' = $NodeUrl
|
||
}
|
||
}
|
||
|
||
function Start-Application {
|
||
param($Config, [string]$Token, [string]$NodeUrl, [string]$Ip)
|
||
|
||
$query = Join-RequestPairs ([ordered]@{
|
||
airportCode = $Config.AIRPORT_CODE
|
||
targetIp = $Ip
|
||
applicationName = $Config.APP_NAME
|
||
moduleName = $Config.MODULE_NAME
|
||
runStart = 'true'
|
||
})
|
||
|
||
[void](Invoke-PamWebRequest -Method POST -Url "$($Config.HOME_BASE_URL)/node-proxy/$($Config.AIRPORT_CODE)/api/mcp/version/upgrade/start-stop?$query" -Token $Token -Headers @{
|
||
'Target-Node' = $NodeUrl
|
||
})
|
||
}
|
||
|
||
function Stop-Application {
|
||
param($Config, [string]$Token, [string]$NodeUrl, [string]$Ip)
|
||
|
||
$query = Join-RequestPairs ([ordered]@{
|
||
airportCode = $Config.AIRPORT_CODE
|
||
targetIp = $Ip
|
||
applicationName = $Config.APP_NAME
|
||
moduleName = $Config.MODULE_NAME
|
||
runStart = 'false'
|
||
})
|
||
|
||
[void](Invoke-PamWebRequest -Method POST -Url "$($Config.HOME_BASE_URL)/node-proxy/$($Config.AIRPORT_CODE)/api/mcp/version/upgrade/start-stop?$query" -Token $Token -Headers @{
|
||
'Target-Node' = $NodeUrl
|
||
})
|
||
}
|
||
|
||
function Verify-Ip {
|
||
param($Config, [string]$Token, [string]$NodeUrl, [string]$Ip)
|
||
|
||
$query = Join-RequestPairs ([ordered]@{
|
||
applicationName = $Config.APP_NAME
|
||
moduleName = $Config.MODULE_NAME
|
||
airportCode = $Config.AIRPORT_CODE
|
||
targetIp = $Ip
|
||
})
|
||
|
||
Invoke-PamWebRequest -Method GET -Url "$($Config.HOME_BASE_URL)/node-proxy/$($Config.AIRPORT_CODE)/api/mcp/version/upgrade/verify?$query" -Token $Token -Headers @{
|
||
'Target-Node' = $NodeUrl
|
||
}
|
||
}
|
||
|
||
function Download-DeployLog {
|
||
param($Config, [string]$Token, [string]$NodeUrl, [string]$Ip)
|
||
|
||
$logsDir = Join-Path $PSScriptRoot 'logs'
|
||
if (-not (Test-Path -LiteralPath $logsDir)) {
|
||
$null = New-Item -ItemType Directory -Path $logsDir
|
||
}
|
||
|
||
$logFile = Join-Path $logsDir ("deploy_{0}.zip" -f $Ip)
|
||
$errorFile = Join-Path $logsDir ("error_{0}.log" -f $Ip)
|
||
$query = Join-RequestPairs ([ordered]@{
|
||
applicationName = $Config.APP_NAME
|
||
moduleName = $Config.MODULE_NAME
|
||
airportCode = $Config.AIRPORT_CODE
|
||
targetIp = $Ip
|
||
logName = $Config.LOG_NAME
|
||
})
|
||
|
||
try {
|
||
[void](Invoke-PamWebRequest -Method GET -Url "$($Config.HOME_BASE_URL)/node-proxy/$($Config.AIRPORT_CODE)/api/mcp/version/upgrade/log-download?$query" -Token $Token -Headers @{
|
||
'Target-Node' = $NodeUrl
|
||
} -OutFile $logFile)
|
||
|
||
if ((Get-Item -LiteralPath $logFile).Length -gt 0) {
|
||
@(
|
||
'Archive format: zip'
|
||
("Saved path: {0}" -f $logFile)
|
||
("Size: {0} bytes" -f (Get-Item -LiteralPath $logFile).Length)
|
||
) | Set-Content -LiteralPath "$logFile.summary"
|
||
} else {
|
||
'Zip archive empty or no data' | Set-Content -LiteralPath "$logFile.summary"
|
||
}
|
||
} catch {
|
||
Get-ErrorBody $_ | Set-Content -LiteralPath $errorFile
|
||
"Log download failed. See $errorFile" | Set-Content -LiteralPath $logFile
|
||
'Log download failed' | Set-Content -LiteralPath "$logFile.summary"
|
||
}
|
||
|
||
return $logFile
|
||
}
|
||
|
||
function Invoke-Rollback {
|
||
param($Config, [string]$Token, [string]$NodeUrl, [string]$Ip, [bool]$StopFirst)
|
||
|
||
if ($StopFirst) {
|
||
try {
|
||
Stop-Application -Config $Config -Token $Token -NodeUrl $NodeUrl -Ip $Ip
|
||
} catch {
|
||
}
|
||
}
|
||
|
||
try {
|
||
$body = Join-RequestPairs ([ordered]@{
|
||
airportCode = $Config.AIRPORT_CODE
|
||
targetIp = $Ip
|
||
applicationName = $Config.APP_NAME
|
||
moduleName = $Config.MODULE_NAME
|
||
timeOut = $Config.TIMEOUT
|
||
})
|
||
$response = Invoke-PamWebRequest -Method POST -Url "$($Config.HOME_BASE_URL)/node-proxy/$($Config.AIRPORT_CODE)/api/mcp/version/upgrade/rollback" -Token $Token -Headers @{
|
||
'Target-Node' = $NodeUrl
|
||
} -Body $body -ContentType 'application/x-www-form-urlencoded'
|
||
|
||
$rollbackSuccess = Get-ResponseValue -Response $response -Candidates @('success')
|
||
if ($rollbackSuccess -and $rollbackSuccess -ne 'true') {
|
||
return 'ROLLBACK_FAILED'
|
||
}
|
||
} catch {
|
||
return 'ROLLBACK_REQUEST_FAILED'
|
||
}
|
||
|
||
try {
|
||
$verify = Verify-Ip -Config $Config -Token $Token -NodeUrl $NodeUrl -Ip $Ip
|
||
if ((Get-ResponseValue -Response $verify -Candidates @('success')) -eq 'true') {
|
||
return 'ROLLBACK_SUCCESS'
|
||
}
|
||
return 'ROLLBACK_VERIFY_FAILED'
|
||
} catch {
|
||
return 'ROLLBACK_VERIFY_FAILED'
|
||
}
|
||
}
|
||
|
||
function Invoke-IpDeploy {
|
||
param(
|
||
$Config,
|
||
[string]$Token,
|
||
[string]$NodeUrl,
|
||
[string]$Ip
|
||
)
|
||
|
||
Write-Info "Processing IP: $Ip"
|
||
|
||
try {
|
||
$upgrade = Invoke-FlowStep -Name "Invoke-UpgradeRequest[$Ip]" -Action {
|
||
Invoke-UpgradeRequest -Config $Config -Token $Token -NodeUrl $NodeUrl -Ip $Ip
|
||
}
|
||
} catch {
|
||
$logFile = Invoke-FlowStep -Name "Download-DeployLog[$Ip]" -Action {
|
||
Download-DeployLog -Config $Config -Token $Token -NodeUrl $NodeUrl -Ip $Ip
|
||
}
|
||
return [pscustomobject]@{
|
||
Ip = $Ip
|
||
Status = 'FAILED'
|
||
Stage = 'UPGRADE'
|
||
Message = 'Upgrade request failed'
|
||
Rollback = 'ROLLBACK_NOT_RUN'
|
||
LogFile = $logFile
|
||
}
|
||
}
|
||
|
||
if ((Get-ResponseValue -Response $upgrade -Candidates @('success')) -ne 'true') {
|
||
$message = Get-ResponseValue -Response $upgrade -Candidates @('message')
|
||
if (-not $message) { $message = 'Upgrade failed' }
|
||
$rollback = Get-PendingRollbackStatus -Ip $Ip -Stage 'UPGRADE' -StopFirst:$false -Reason $message
|
||
$logFile = Invoke-FlowStep -Name "Download-DeployLog[$Ip]" -Action {
|
||
Download-DeployLog -Config $Config -Token $Token -NodeUrl $NodeUrl -Ip $Ip
|
||
}
|
||
return [pscustomobject]@{
|
||
Ip = $Ip
|
||
Status = 'FAILED'
|
||
Stage = 'UPGRADE'
|
||
Message = $message
|
||
Rollback = $rollback
|
||
LogFile = $logFile
|
||
}
|
||
}
|
||
|
||
try {
|
||
Invoke-FlowStep -Name "Start-Application[$Ip]" -Action {
|
||
Start-Application -Config $Config -Token $Token -NodeUrl $NodeUrl -Ip $Ip
|
||
} | Out-Null
|
||
} catch {
|
||
$rollback = Get-PendingRollbackStatus -Ip $Ip -Stage 'START' -StopFirst:$true -Reason 'Application start failed'
|
||
$logFile = Invoke-FlowStep -Name "Download-DeployLog[$Ip]" -Action {
|
||
Download-DeployLog -Config $Config -Token $Token -NodeUrl $NodeUrl -Ip $Ip
|
||
}
|
||
return [pscustomobject]@{
|
||
Ip = $Ip
|
||
Status = 'FAILED'
|
||
Stage = 'START'
|
||
Message = 'Application start failed'
|
||
Rollback = $rollback
|
||
LogFile = $logFile
|
||
}
|
||
}
|
||
|
||
try {
|
||
$verify = Invoke-FlowStep -Name "Verify-Ip[$Ip]" -Action {
|
||
Verify-Ip -Config $Config -Token $Token -NodeUrl $NodeUrl -Ip $Ip
|
||
}
|
||
} catch {
|
||
$rollback = Get-PendingRollbackStatus -Ip $Ip -Stage 'VERIFY' -StopFirst:$true -Reason 'Health check request failed'
|
||
$logFile = Invoke-FlowStep -Name "Download-DeployLog[$Ip]" -Action {
|
||
Download-DeployLog -Config $Config -Token $Token -NodeUrl $NodeUrl -Ip $Ip
|
||
}
|
||
return [pscustomobject]@{
|
||
Ip = $Ip
|
||
Status = 'FAILED'
|
||
Stage = 'VERIFY'
|
||
Message = 'Health check request failed'
|
||
Rollback = $rollback
|
||
LogFile = $logFile
|
||
}
|
||
}
|
||
|
||
if ((Get-ResponseValue -Response $verify -Candidates @('success')) -eq 'true') {
|
||
$logFile = Invoke-FlowStep -Name "Download-DeployLog[$Ip]" -Action {
|
||
Download-DeployLog -Config $Config -Token $Token -NodeUrl $NodeUrl -Ip $Ip
|
||
}
|
||
return [pscustomobject]@{
|
||
Ip = $Ip
|
||
Status = 'SUCCESS'
|
||
Stage = '-'
|
||
Message = '-'
|
||
Rollback = '-'
|
||
LogFile = $logFile
|
||
}
|
||
}
|
||
|
||
$message = Get-ResponseValue -Response $verify -Candidates @('message')
|
||
if (-not $message) { $message = 'Health check failed' }
|
||
$rollback = Get-PendingRollbackStatus -Ip $Ip -Stage 'VERIFY' -StopFirst:$true -Reason $message
|
||
$logFile = Invoke-FlowStep -Name "Download-DeployLog[$Ip]" -Action {
|
||
Download-DeployLog -Config $Config -Token $Token -NodeUrl $NodeUrl -Ip $Ip
|
||
}
|
||
return [pscustomobject]@{
|
||
Ip = $Ip
|
||
Status = 'FAILED'
|
||
Stage = 'VERIFY'
|
||
Message = $message
|
||
Rollback = $rollback
|
||
LogFile = $logFile
|
||
}
|
||
}
|
||
|
||
function Write-DeployReport {
|
||
param(
|
||
$Config,
|
||
[System.Collections.Generic.List[object]]$Results,
|
||
[int]$TotalCount
|
||
)
|
||
|
||
$successCount = @($Results | Where-Object { $_.Status -eq 'SUCCESS' }).Count
|
||
$failCount = @($Results | Where-Object { $_.Status -ne 'SUCCESS' }).Count
|
||
|
||
Write-Host ''
|
||
Write-Host '====================== DEPLOY REPORT ======================'
|
||
Write-Host 'Mode: Batch/PowerShell'
|
||
Write-Host "Airport: $($Config.AIRPORT_CODE)"
|
||
Write-Host "Application: $($Config.APP_NAME)"
|
||
Write-Host "Module: $($Config.MODULE_NAME)"
|
||
Write-Host "Version: $($Config.VERSION_NUMBER)"
|
||
Write-Host "Total: $TotalCount"
|
||
Write-Host "Success: $successCount"
|
||
Write-Host "Failed: $failCount"
|
||
Write-Host ''
|
||
Write-Host ('{0,-18} {1,-8} {2,-12} {3,-22} {4}' -f 'IP', 'STATUS', 'STAGE', 'ROLLBACK', 'LOG')
|
||
foreach ($item in $Results) {
|
||
Write-Host ('{0,-18} {1,-8} {2,-12} {3,-22} {4}' -f $item.Ip, $item.Status, $item.Stage, $item.Rollback, $item.LogFile)
|
||
if ($item.Status -ne 'SUCCESS') {
|
||
Write-Host (" Reason: {0}" -f $item.Message)
|
||
}
|
||
}
|
||
}
|
||
|
||
function Invoke-PamDeploy {
|
||
param([string]$ConfigPath)
|
||
|
||
$script:ActiveConfigPath = $ConfigPath
|
||
$config = Invoke-FlowStep -Name 'Get-PamConfig' -Detail "path=$ConfigPath" -Action {
|
||
Get-PamConfig -Path $ConfigPath
|
||
}
|
||
Invoke-FlowStep -Name 'Test-ZipFile' -Action {
|
||
Test-ZipFile -Config $config
|
||
} | Out-Null
|
||
|
||
Write-Info "Deploy start: airport=$($config.AIRPORT_CODE), version=$($config.VERSION_NUMBER), module=$($config.APP_NAME)/$($config.MODULE_NAME)"
|
||
|
||
$token = Invoke-FlowStep -Name 'Get-Token' -Action {
|
||
Get-Token -Config $config
|
||
}
|
||
Invoke-FlowStep -Name 'New-VersionRecord' -Action {
|
||
New-VersionRecord -Config $config -Token $token
|
||
} | Out-Null
|
||
$hashCode = Invoke-FlowStep -Name 'Upload-Package' -Action {
|
||
Upload-Package -Config $config -Token $token
|
||
}
|
||
Invoke-FlowStep -Name 'Publish-Version' -Action {
|
||
Publish-Version -Config $config -Token $token -HashCode $hashCode
|
||
} | Out-Null
|
||
$nodeUrl = Invoke-FlowStep -Name 'Get-NodeUrl' -Action {
|
||
Get-NodeUrl -Config $config -Token $token
|
||
}
|
||
$ips = Invoke-FlowStep -Name 'Get-OnlineIps' -Action {
|
||
Get-OnlineIps -Config $config -Token $token -NodeUrl $nodeUrl
|
||
}
|
||
Invoke-FlowStep -Name 'Download-CloudToNode' -Action {
|
||
Download-CloudToNode -Config $config -Token $token -NodeUrl $nodeUrl
|
||
} | Out-Null
|
||
|
||
$results = [System.Collections.Generic.List[object]]::new()
|
||
foreach ($ip in $ips) {
|
||
$results.Add((Invoke-IpDeploy -Config $config -Token $token -NodeUrl $nodeUrl -Ip $ip))
|
||
}
|
||
|
||
Write-DeployReport -Config $config -Results $results -TotalCount $ips.Count
|
||
}
|
||
|
||
function Invoke-PamManualRollback {
|
||
param(
|
||
[string]$ConfigPath,
|
||
[string]$Ip,
|
||
[bool]$StopFirst
|
||
)
|
||
|
||
$script:ActiveConfigPath = $ConfigPath
|
||
$config = Invoke-FlowStep -Name 'Get-PamConfig' -Detail "path=$ConfigPath" -Action {
|
||
Get-PamConfig -Path $ConfigPath
|
||
}
|
||
|
||
Write-Info "Manual rollback start: airport=$($config.AIRPORT_CODE), ip=$Ip, stopFirst=$StopFirst"
|
||
$token = Invoke-FlowStep -Name 'Get-Token' -Action {
|
||
Get-Token -Config $config
|
||
}
|
||
$nodeUrl = Invoke-FlowStep -Name 'Get-NodeUrl' -Action {
|
||
Get-NodeUrl -Config $config -Token $token
|
||
}
|
||
$result = Invoke-FlowStep -Name "Invoke-Rollback[$Ip]" -Action {
|
||
Invoke-Rollback -Config $config -Token $token -NodeUrl $nodeUrl -Ip $Ip -StopFirst:$StopFirst
|
||
}
|
||
|
||
Write-Info "Manual rollback done: ip=$Ip result=$result"
|
||
Write-Host "ROLLBACK RESULT: $result"
|
||
}
|
||
|
||
function Invoke-PamAction {
|
||
param(
|
||
[string]$ConfigPath,
|
||
[string]$Action,
|
||
[string]$Ip,
|
||
[string]$HashCode,
|
||
[bool]$StopFirst
|
||
)
|
||
|
||
$script:ActiveConfigPath = $ConfigPath
|
||
$config = Invoke-FlowStep -Name 'Get-PamConfig' -Detail "path=$ConfigPath" -Action {
|
||
Get-PamConfig -Path $ConfigPath
|
||
}
|
||
|
||
switch ($Action.ToLowerInvariant()) {
|
||
'get-token' {
|
||
$token = Invoke-FlowStep -Name 'Get-Token' -Action { Get-Token -Config $config }
|
||
Write-ResultLine -Key 'ACTION' -Value 'get-token'
|
||
Write-ResultLine -Key 'TOKEN' -Value $token
|
||
}
|
||
'create-version' {
|
||
$token = Invoke-FlowStep -Name 'Get-Token' -Action { Get-Token -Config $config }
|
||
Invoke-FlowStep -Name 'New-VersionRecord' -Action { New-VersionRecord -Config $config -Token $token } | Out-Null
|
||
Write-ResultLine -Key 'ACTION' -Value 'create-version'
|
||
Write-ResultLine -Key 'VERSION_NUMBER' -Value $config.VERSION_NUMBER
|
||
Write-ResultLine -Key 'RESULT' -Value 'OK'
|
||
}
|
||
'upload-package' {
|
||
Invoke-FlowStep -Name 'Test-ZipFile' -Action { Test-ZipFile -Config $config } | Out-Null
|
||
$token = Invoke-FlowStep -Name 'Get-Token' -Action { Get-Token -Config $config }
|
||
$hash = Invoke-FlowStep -Name 'Upload-Package' -Action { Upload-Package -Config $config -Token $token }
|
||
Write-ResultLine -Key 'ACTION' -Value 'upload-package'
|
||
Write-ResultLine -Key 'HASH_CODE' -Value $hash
|
||
}
|
||
'publish-version' {
|
||
Require-HashCodeArgument -PublishHashCode $HashCode
|
||
$token = Invoke-FlowStep -Name 'Get-Token' -Action { Get-Token -Config $config }
|
||
Invoke-FlowStep -Name 'Publish-Version' -Action { Publish-Version -Config $config -Token $token -HashCode $HashCode } | Out-Null
|
||
Write-ResultLine -Key 'ACTION' -Value 'publish-version'
|
||
Write-ResultLine -Key 'HASH_CODE' -Value $HashCode
|
||
Write-ResultLine -Key 'RESULT' -Value 'OK'
|
||
}
|
||
'get-node-url' {
|
||
$token = Invoke-FlowStep -Name 'Get-Token' -Action { Get-Token -Config $config }
|
||
$nodeUrl = Invoke-FlowStep -Name 'Get-NodeUrl' -Action { Get-NodeUrl -Config $config -Token $token }
|
||
Write-ResultLine -Key 'ACTION' -Value 'get-node-url'
|
||
Write-ResultLine -Key 'NODE_URL' -Value $nodeUrl
|
||
}
|
||
'get-online-ips' {
|
||
$token = Invoke-FlowStep -Name 'Get-Token' -Action { Get-Token -Config $config }
|
||
$nodeUrl = Invoke-FlowStep -Name 'Get-NodeUrl' -Action { Get-NodeUrl -Config $config -Token $token }
|
||
$ips = Invoke-FlowStep -Name 'Get-OnlineIps' -Action { Get-OnlineIps -Config $config -Token $token -NodeUrl $nodeUrl }
|
||
Write-OnlineIpsResult -Ips @($ips)
|
||
}
|
||
'create-download-task' {
|
||
$token = Invoke-FlowStep -Name 'Get-Token' -Action { Get-Token -Config $config }
|
||
$nodeUrl = Invoke-FlowStep -Name 'Get-NodeUrl' -Action { Get-NodeUrl -Config $config -Token $token }
|
||
Invoke-FlowStep -Name 'Create-DownloadTask' -Action { Create-DownloadTask -Config $config -Token $token -NodeUrl $nodeUrl } | Out-Null
|
||
Write-ResultLine -Key 'ACTION' -Value 'create-download-task'
|
||
Write-ResultLine -Key 'TIME_OUT' -Value '0'
|
||
Write-ResultLine -Key 'RESULT' -Value 'TASK_CREATED'
|
||
}
|
||
'poll-download-progress' {
|
||
$token = Invoke-FlowStep -Name 'Get-Token' -Action { Get-Token -Config $config }
|
||
$nodeUrl = Invoke-FlowStep -Name 'Get-NodeUrl' -Action { Get-NodeUrl -Config $config -Token $token }
|
||
Invoke-FlowStep -Name 'Wait-DownloadProgress' -Action { Wait-DownloadProgress -Config $config -Token $token -NodeUrl $nodeUrl } | Out-Null
|
||
Write-DownloadProgressResult
|
||
}
|
||
'download-cloud-to-node' {
|
||
$token = Invoke-FlowStep -Name 'Get-Token' -Action { Get-Token -Config $config }
|
||
$nodeUrl = Invoke-FlowStep -Name 'Get-NodeUrl' -Action { Get-NodeUrl -Config $config -Token $token }
|
||
Invoke-FlowStep -Name 'Download-CloudToNode' -Action { Download-CloudToNode -Config $config -Token $token -NodeUrl $nodeUrl } | Out-Null
|
||
Write-DownloadProgressResult -ActionName 'download-cloud-to-node'
|
||
Write-ResultLine -Key 'RESULT' -Value 'DONE'
|
||
}
|
||
'upgrade-ip' {
|
||
Require-IpArgument -TargetIp $Ip
|
||
$token = Invoke-FlowStep -Name 'Get-Token' -Action { Get-Token -Config $config }
|
||
$nodeUrl = Invoke-FlowStep -Name 'Get-NodeUrl' -Action { Get-NodeUrl -Config $config -Token $token }
|
||
$response = Invoke-FlowStep -Name "Invoke-UpgradeRequest[$Ip]" -Action { Invoke-UpgradeRequest -Config $config -Token $token -NodeUrl $nodeUrl -Ip $Ip }
|
||
Write-ResultLine -Key 'ACTION' -Value 'upgrade-ip'
|
||
Write-ResultLine -Key 'IP' -Value $Ip
|
||
Write-ResultLine -Key 'SUCCESS' -Value (Get-ResponseValue -Response $response -Candidates @('success'))
|
||
Write-ResultLine -Key 'MESSAGE' -Value (Get-ResponseValue -Response $response -Candidates @('message'))
|
||
Write-ResultLine -Key 'RAW_RESPONSE' -Value ([string]$response)
|
||
}
|
||
'start-ip' {
|
||
Require-IpArgument -TargetIp $Ip
|
||
$token = Invoke-FlowStep -Name 'Get-Token' -Action { Get-Token -Config $config }
|
||
$nodeUrl = Invoke-FlowStep -Name 'Get-NodeUrl' -Action { Get-NodeUrl -Config $config -Token $token }
|
||
Invoke-FlowStep -Name "Start-Application[$Ip]" -Action { Start-Application -Config $config -Token $token -NodeUrl $nodeUrl -Ip $Ip } | Out-Null
|
||
Write-ResultLine -Key 'ACTION' -Value 'start-ip'
|
||
Write-ResultLine -Key 'IP' -Value $Ip
|
||
Write-ResultLine -Key 'RUN_START' -Value 'true'
|
||
Write-ResultLine -Key 'RESULT' -Value 'OK'
|
||
}
|
||
'stop-ip' {
|
||
Require-IpArgument -TargetIp $Ip
|
||
$token = Invoke-FlowStep -Name 'Get-Token' -Action { Get-Token -Config $config }
|
||
$nodeUrl = Invoke-FlowStep -Name 'Get-NodeUrl' -Action { Get-NodeUrl -Config $config -Token $token }
|
||
Invoke-FlowStep -Name "Stop-Application[$Ip]" -Action { Stop-Application -Config $config -Token $token -NodeUrl $nodeUrl -Ip $Ip } | Out-Null
|
||
Write-ResultLine -Key 'ACTION' -Value 'stop-ip'
|
||
Write-ResultLine -Key 'IP' -Value $Ip
|
||
Write-ResultLine -Key 'RUN_START' -Value 'false'
|
||
Write-ResultLine -Key 'RESULT' -Value 'OK'
|
||
}
|
||
'verify-ip' {
|
||
Require-IpArgument -TargetIp $Ip
|
||
$token = Invoke-FlowStep -Name 'Get-Token' -Action { Get-Token -Config $config }
|
||
$nodeUrl = Invoke-FlowStep -Name 'Get-NodeUrl' -Action { Get-NodeUrl -Config $config -Token $token }
|
||
$response = Invoke-FlowStep -Name "Verify-Ip[$Ip]" -Action { Verify-Ip -Config $config -Token $token -NodeUrl $nodeUrl -Ip $Ip }
|
||
Write-ResultLine -Key 'ACTION' -Value 'verify-ip'
|
||
Write-ResultLine -Key 'IP' -Value $Ip
|
||
Write-ResultLine -Key 'SUCCESS' -Value (Get-ResponseValue -Response $response -Candidates @('success'))
|
||
Write-ResultLine -Key 'MESSAGE' -Value (Get-ResponseValue -Response $response -Candidates @('message'))
|
||
Write-ResultLine -Key 'RAW_RESPONSE' -Value ([string]$response)
|
||
}
|
||
'download-log' {
|
||
Require-IpArgument -TargetIp $Ip
|
||
$token = Invoke-FlowStep -Name 'Get-Token' -Action { Get-Token -Config $config }
|
||
$nodeUrl = Invoke-FlowStep -Name 'Get-NodeUrl' -Action { Get-NodeUrl -Config $config -Token $token }
|
||
$logFile = Invoke-FlowStep -Name "Download-DeployLog[$Ip]" -Action { Download-DeployLog -Config $config -Token $token -NodeUrl $nodeUrl -Ip $Ip }
|
||
Write-ResultLine -Key 'ACTION' -Value 'download-log'
|
||
Write-ResultLine -Key 'IP' -Value $Ip
|
||
Write-ResultLine -Key 'LOG_FILE' -Value $logFile
|
||
}
|
||
'rollback-ip' {
|
||
Require-IpArgument -TargetIp $Ip
|
||
$token = Invoke-FlowStep -Name 'Get-Token' -Action { Get-Token -Config $config }
|
||
$nodeUrl = Invoke-FlowStep -Name 'Get-NodeUrl' -Action { Get-NodeUrl -Config $config -Token $token }
|
||
$rollbackResult = Invoke-FlowStep -Name "Invoke-Rollback[$Ip]" -Action { Invoke-Rollback -Config $config -Token $token -NodeUrl $nodeUrl -Ip $Ip -StopFirst:$StopFirst }
|
||
Write-ResultLine -Key 'ACTION' -Value 'rollback-ip'
|
||
Write-ResultLine -Key 'IP' -Value $Ip
|
||
Write-ResultLine -Key 'STOP_FIRST' -Value ($StopFirst.ToString().ToLowerInvariant())
|
||
Write-ResultLine -Key 'ROLLBACK_RESULT' -Value $rollbackResult
|
||
}
|
||
default {
|
||
throw "Unknown action: $Action"
|
||
}
|
||
}
|
||
}
|
||
|
||
if ($Help) {
|
||
Show-DeployUsage
|
||
exit 0
|
||
}
|
||
|
||
if ($MyInvocation.InvocationName -ne '.') {
|
||
try {
|
||
if ($Action) {
|
||
Invoke-PamAction -ConfigPath $ConfigPath -Action $Action -Ip $Ip -HashCode $HashCode -StopFirst:$RollbackStopFirst.IsPresent
|
||
} elseif ($RollbackIp) {
|
||
Invoke-PamManualRollback -ConfigPath $ConfigPath -Ip $RollbackIp -StopFirst:$RollbackStopFirst.IsPresent
|
||
} else {
|
||
Invoke-PamDeploy -ConfigPath $ConfigPath
|
||
}
|
||
} catch {
|
||
Write-ErrLog $_
|
||
exit 1
|
||
}
|
||
}
|