param( [Alias('ConfigPath')] [string]$TestConfigPath = (Join-Path $PSScriptRoot 'config.txt'), [ValidateSet('smoke', 'full')] [string]$Mode = 'full', [switch]$SkipRollback, [int]$MaxIps = 0, [switch]$Help ) # PAM 测试脚本(PowerShell 实现)。 Set-StrictMode -Version Latest $ErrorActionPreference = 'Stop' if ($Help) { @' Usage: powershell -File .\test_deploy.ps1 [-ConfigPath .\config.txt] [-Mode smoke|full] [-SkipRollback] [-MaxIps N] Modes: smoke - only test config, token, node, and online IP lookup full - test all deployment interfaces in workflow order Notes: - full mode tests create version, upload, publish, node download, upgrade, start, verify, and log download - rollback is tested once by default in full mode - use -SkipRollback if you do not want the test script to change the deployed state - use -MaxIps to limit how many online IPs are used for interface testing '@ | Write-Host exit 0 } . (Join-Path $PSScriptRoot 'deploy.ps1') function Add-TestResult { param( [System.Collections.Generic.List[object]]$Results, [string]$Step, [string]$Status, [string]$Detail ) $Results.Add([pscustomobject]@{ Step = $Step Status = $Status Detail = $Detail }) | Out-Null } function Write-TestReport { param([System.Collections.Generic.List[object]]$Results) $passCount = @($Results | Where-Object { $_.Status -eq 'PASS' }).Count $failCount = @($Results | Where-Object { $_.Status -eq 'FAIL' }).Count $skipCount = @($Results | Where-Object { $_.Status -eq 'SKIP' }).Count Write-Host '' Write-Host '====================== API TEST REPORT ======================' Write-Host "PASS: $passCount" Write-Host "FAIL: $failCount" Write-Host "SKIP: $skipCount" Write-Host '' Write-Host ('{0,-28} {1,-8} {2}' -f 'STEP', 'STATUS', 'DETAIL') foreach ($item in $Results) { Write-Host ('{0,-28} {1,-8} {2}' -f $item.Step, $item.Status, $item.Detail) } } function Invoke-PamSmokeTest { param([string]$ConfigPath) $results = [System.Collections.Generic.List[object]]::new() $config = Get-PamConfig -Path $ConfigPath try { Test-ZipFile -Config $config Add-TestResult -Results $results -Step 'ZIP_FILE' -Status 'PASS' -Detail $config.ZIP_FILE_PATH } catch { Add-TestResult -Results $results -Step 'ZIP_FILE' -Status 'FAIL' -Detail $_.Exception.Message Write-TestReport -Results $results throw } try { $token = Get-Token -Config $config Add-TestResult -Results $results -Step 'TOKEN' -Status 'PASS' -Detail ('token length={0}' -f $token.Length) } catch { Add-TestResult -Results $results -Step 'TOKEN' -Status 'FAIL' -Detail $_.Exception.Message Write-TestReport -Results $results throw } try { $nodeUrl = Get-NodeUrl -Config $config -Token $token Add-TestResult -Results $results -Step 'TARGET_NODE' -Status 'PASS' -Detail $nodeUrl } catch { Add-TestResult -Results $results -Step 'TARGET_NODE' -Status 'FAIL' -Detail $_.Exception.Message Write-TestReport -Results $results throw } try { $ips = Get-OnlineIps -Config $config -Token $token -NodeUrl $nodeUrl Add-TestResult -Results $results -Step 'ONLINE_IPS' -Status 'PASS' -Detail (($ips -join ', ')) } catch { Add-TestResult -Results $results -Step 'ONLINE_IPS' -Status 'FAIL' -Detail $_.Exception.Message Write-TestReport -Results $results throw } Write-TestReport -Results $results } function Invoke-PamFullTest { param( [string]$ConfigPath, [bool]$ShouldSkipRollback, [int]$MaxIps ) $results = [System.Collections.Generic.List[object]]::new() $config = Get-PamConfig -Path $ConfigPath try { Test-ZipFile -Config $config Add-TestResult -Results $results -Step 'ZIP_FILE' -Status 'PASS' -Detail $config.ZIP_FILE_PATH } catch { Add-TestResult -Results $results -Step 'ZIP_FILE' -Status 'FAIL' -Detail $_.Exception.Message Write-TestReport -Results $results throw } try { $token = Get-Token -Config $config Add-TestResult -Results $results -Step 'TOKEN' -Status 'PASS' -Detail ('token length={0}' -f $token.Length) } catch { Add-TestResult -Results $results -Step 'TOKEN' -Status 'FAIL' -Detail $_.Exception.Message Write-TestReport -Results $results throw } try { New-VersionRecord -Config $config -Token $token Add-TestResult -Results $results -Step 'CREATE_VERSION' -Status 'PASS' -Detail $config.VERSION_NUMBER } catch { Add-TestResult -Results $results -Step 'CREATE_VERSION' -Status 'FAIL' -Detail $_.Exception.Message Write-TestReport -Results $results throw } try { $hashCode = Upload-Package -Config $config -Token $token Add-TestResult -Results $results -Step 'UPLOAD_PACKAGE' -Status 'PASS' -Detail $hashCode } catch { Add-TestResult -Results $results -Step 'UPLOAD_PACKAGE' -Status 'FAIL' -Detail $_.Exception.Message Write-TestReport -Results $results throw } try { Publish-Version -Config $config -Token $token -HashCode $hashCode Add-TestResult -Results $results -Step 'PUBLISH_VERSION' -Status 'PASS' -Detail $config.AIRPORT_CODE } catch { Add-TestResult -Results $results -Step 'PUBLISH_VERSION' -Status 'FAIL' -Detail $_.Exception.Message Write-TestReport -Results $results throw } try { $nodeUrl = Get-NodeUrl -Config $config -Token $token Add-TestResult -Results $results -Step 'TARGET_NODE' -Status 'PASS' -Detail $nodeUrl } catch { Add-TestResult -Results $results -Step 'TARGET_NODE' -Status 'FAIL' -Detail $_.Exception.Message Write-TestReport -Results $results throw } try { $ips = Get-OnlineIps -Config $config -Token $token -NodeUrl $nodeUrl Add-TestResult -Results $results -Step 'ONLINE_IPS' -Status 'PASS' -Detail (($ips -join ', ')) } catch { Add-TestResult -Results $results -Step 'ONLINE_IPS' -Status 'FAIL' -Detail $_.Exception.Message Write-TestReport -Results $results throw } try { Download-CloudToNode -Config $config -Token $token -NodeUrl $nodeUrl Add-TestResult -Results $results -Step 'DOWNLOAD_TO_NODE' -Status 'PASS' -Detail $config.VERSION_NUMBER } catch { Add-TestResult -Results $results -Step 'DOWNLOAD_TO_NODE' -Status 'FAIL' -Detail $_.Exception.Message Write-TestReport -Results $results throw } $testIps = @($ips) if ($MaxIps -gt 0) { $testIps = @($ips | Select-Object -First $MaxIps) } $rollbackTested = $false foreach ($ip in $testIps) { try { $upgradeResponse = Invoke-UpgradeRequest -Config $config -Token $token -NodeUrl $nodeUrl -Ip $ip $upgradeSuccess = Get-ResponseValue -Response $upgradeResponse -Candidates @('success') $upgradeMessage = Get-ResponseValue -Response $upgradeResponse -Candidates @('message') if ($upgradeSuccess -eq 'true') { Add-TestResult -Results $results -Step "UPGRADE [$ip]" -Status 'PASS' -Detail 'success=true' } else { if (-not $upgradeMessage) { $upgradeMessage = 'success != true' } Add-TestResult -Results $results -Step "UPGRADE [$ip]" -Status 'FAIL' -Detail $upgradeMessage } } catch { Add-TestResult -Results $results -Step "UPGRADE [$ip]" -Status 'FAIL' -Detail $_.Exception.Message } try { Start-Application -Config $config -Token $token -NodeUrl $nodeUrl -Ip $ip Add-TestResult -Results $results -Step "START [$ip]" -Status 'PASS' -Detail 'request completed' } catch { Add-TestResult -Results $results -Step "START [$ip]" -Status 'FAIL' -Detail $_.Exception.Message } try { $verifyResponse = Verify-Ip -Config $config -Token $token -NodeUrl $nodeUrl -Ip $ip $verifySuccess = Get-ResponseValue -Response $verifyResponse -Candidates @('success') $verifyMessage = Get-ResponseValue -Response $verifyResponse -Candidates @('message') if ($verifySuccess -eq 'true') { Add-TestResult -Results $results -Step "VERIFY [$ip]" -Status 'PASS' -Detail 'success=true' } else { if (-not $verifyMessage) { $verifyMessage = 'success != true' } Add-TestResult -Results $results -Step "VERIFY [$ip]" -Status 'FAIL' -Detail $verifyMessage } } catch { Add-TestResult -Results $results -Step "VERIFY [$ip]" -Status 'FAIL' -Detail $_.Exception.Message } try { $logFile = Download-DeployLog -Config $config -Token $token -NodeUrl $nodeUrl -Ip $ip Add-TestResult -Results $results -Step "LOG_DOWNLOAD [$ip]" -Status 'PASS' -Detail $logFile } catch { Add-TestResult -Results $results -Step "LOG_DOWNLOAD [$ip]" -Status 'FAIL' -Detail $_.Exception.Message } if (-not $ShouldSkipRollback -and -not $rollbackTested) { try { $rollbackResult = Invoke-Rollback -Config $config -Token $token -NodeUrl $nodeUrl -Ip $ip -StopFirst:$true if ($rollbackResult -eq 'ROLLBACK_SUCCESS') { Add-TestResult -Results $results -Step "ROLLBACK [$ip]" -Status 'PASS' -Detail $rollbackResult } else { Add-TestResult -Results $results -Step "ROLLBACK [$ip]" -Status 'FAIL' -Detail $rollbackResult } } catch { Add-TestResult -Results $results -Step "ROLLBACK [$ip]" -Status 'FAIL' -Detail $_.Exception.Message } $rollbackTested = $true } } if ($ShouldSkipRollback) { Add-TestResult -Results $results -Step 'ROLLBACK' -Status 'SKIP' -Detail 'skipped by parameter' } elseif (-not $rollbackTested) { Add-TestResult -Results $results -Step 'ROLLBACK' -Status 'SKIP' -Detail 'no IP available for rollback test' } Write-TestReport -Results $results if (@($results | Where-Object { $_.Status -eq 'FAIL' }).Count -gt 0) { throw 'One or more API tests failed.' } } try { if ($Mode -eq 'smoke') { Invoke-PamSmokeTest -ConfigPath $TestConfigPath } else { Invoke-PamFullTest -ConfigPath $TestConfigPath -ShouldSkipRollback:$SkipRollback.IsPresent -MaxIps $MaxIps } } catch { Write-ErrLog $_ exit 1 }