218 lines
6.2 KiB
PowerShell
218 lines
6.2 KiB
PowerShell
|
|
<#
|
||
|
|
AZA - Step 14: Docker/Compose Smoke-Test (PowerShell 5.1, ASCII-safe)
|
||
|
|
|
||
|
|
Build + start backend via docker compose, wait for /health 200,
|
||
|
|
then run smoke_suite.ps1 against the container.
|
||
|
|
|
||
|
|
Run (from project root OR from deploy folder):
|
||
|
|
cd "C:\Users\surov\Documents\AZA\backup 24.2.26"
|
||
|
|
powershell -ExecutionPolicy Bypass -File .\deploy\docker_smoke.ps1
|
||
|
|
|
||
|
|
Optional parameters:
|
||
|
|
-BaseUrl http://127.0.0.1:8000
|
||
|
|
-WaitSeconds 90
|
||
|
|
-DownAfter (stop containers after test)
|
||
|
|
#>
|
||
|
|
|
||
|
|
[CmdletBinding()]
|
||
|
|
param(
|
||
|
|
[string]$BaseUrl = 'http://127.0.0.1:8000',
|
||
|
|
[int]$WaitSeconds = 60,
|
||
|
|
[switch]$DownAfter
|
||
|
|
)
|
||
|
|
|
||
|
|
$ErrorActionPreference = 'Stop'
|
||
|
|
|
||
|
|
function Write-Info([string]$msg) { Write-Host $msg }
|
||
|
|
function Write-Fail([string]$msg) { Write-Host $msg; exit 1 }
|
||
|
|
|
||
|
|
function Test-DockerServer() {
|
||
|
|
try {
|
||
|
|
$out = & docker version 2>&1
|
||
|
|
if ($LASTEXITCODE -ne 0) { return $false }
|
||
|
|
if (($out -match 'Client:') -and ($out -match 'Server:')) {
|
||
|
|
if ($out -match 'failed to connect to the docker API') { return $false }
|
||
|
|
return $true
|
||
|
|
}
|
||
|
|
return $false
|
||
|
|
} catch { return $false }
|
||
|
|
}
|
||
|
|
|
||
|
|
function Get-DockerContexts() {
|
||
|
|
try {
|
||
|
|
$lines = & docker context ls --format '{{.Name}}' 2>$null
|
||
|
|
if ($LASTEXITCODE -ne 0) { return @() }
|
||
|
|
$ctx = @()
|
||
|
|
foreach ($l in $lines) {
|
||
|
|
$n = ($l | ForEach-Object { $_.Trim() })
|
||
|
|
if ($n) { $ctx += $n }
|
||
|
|
}
|
||
|
|
return $ctx
|
||
|
|
} catch { return @() }
|
||
|
|
}
|
||
|
|
|
||
|
|
function Ensure-DockerRunning([int]$timeoutSec = 180) {
|
||
|
|
if (Test-DockerServer) { return }
|
||
|
|
|
||
|
|
$contexts = Get-DockerContexts
|
||
|
|
$preferred = @('desktop-linux','desktop-windows')
|
||
|
|
foreach ($p in $preferred) {
|
||
|
|
if ($contexts -contains $p) {
|
||
|
|
cmd /c "docker context use $p >nul 2>nul"
|
||
|
|
if (Test-DockerServer) { return }
|
||
|
|
}
|
||
|
|
}
|
||
|
|
foreach ($c in $contexts) {
|
||
|
|
cmd /c "docker context use $c >nul 2>nul"
|
||
|
|
if (Test-DockerServer) { return }
|
||
|
|
}
|
||
|
|
|
||
|
|
$exeCandidates = @(
|
||
|
|
"$env:ProgramFiles\Docker\Docker\Docker Desktop.exe",
|
||
|
|
"${env:ProgramFiles(x86)}\Docker\Docker\Docker Desktop.exe"
|
||
|
|
)
|
||
|
|
$exe = $exeCandidates | Where-Object { $_ -and (Test-Path $_) } | Select-Object -First 1
|
||
|
|
if ($exe) {
|
||
|
|
try {
|
||
|
|
Write-Info '[DOCKER] Starting Docker Desktop...'
|
||
|
|
Start-Process -FilePath $exe | Out-Null
|
||
|
|
} catch { }
|
||
|
|
}
|
||
|
|
|
||
|
|
$deadline = (Get-Date).AddSeconds($timeoutSec)
|
||
|
|
while ((Get-Date) -lt $deadline) {
|
||
|
|
$contexts = Get-DockerContexts
|
||
|
|
foreach ($p in $preferred) {
|
||
|
|
if ($contexts -contains $p) {
|
||
|
|
cmd /c "docker context use $p >nul 2>nul"
|
||
|
|
if (Test-DockerServer) { return }
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (Test-DockerServer) { return }
|
||
|
|
Start-Sleep -Seconds 2
|
||
|
|
}
|
||
|
|
Write-Fail "[FAIL] Docker daemon not reachable after ${timeoutSec}s. Open Docker Desktop and wait until it shows 'Engine running', then rerun this script."
|
||
|
|
}
|
||
|
|
|
||
|
|
# Resolve project root robustly (works from root and from deploy/)
|
||
|
|
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||
|
|
if ((Split-Path -Leaf $ScriptDir) -eq 'deploy') {
|
||
|
|
$Root = Split-Path -Parent $ScriptDir
|
||
|
|
} else {
|
||
|
|
$Root = $ScriptDir
|
||
|
|
}
|
||
|
|
Set-Location -LiteralPath $Root
|
||
|
|
|
||
|
|
$ComposeFile = Join-Path $Root 'deploy\docker-compose.yml'
|
||
|
|
$EnvFile = Join-Path $Root 'deploy\.env'
|
||
|
|
$SmokeScript = Join-Path $Root 'deploy\smoke_suite.ps1'
|
||
|
|
|
||
|
|
Write-Host '[AZA] Step 14 - Docker/Compose Smoke'
|
||
|
|
Write-Host (' Root: ' + $Root)
|
||
|
|
Write-Host (' Compose: ' + $ComposeFile)
|
||
|
|
Write-Host (' EnvFile: ' + $EnvFile)
|
||
|
|
Write-Host (' BaseUrl: ' + $BaseUrl)
|
||
|
|
Write-Host (' Timeout: ' + $WaitSeconds + 's')
|
||
|
|
Write-Host ''
|
||
|
|
|
||
|
|
# Pre-flight checks
|
||
|
|
if (-not (Test-Path -LiteralPath $ComposeFile)) {
|
||
|
|
Write-Host '[FAIL] Compose file not found.'
|
||
|
|
exit 1
|
||
|
|
}
|
||
|
|
if (-not (Test-Path -LiteralPath $EnvFile)) {
|
||
|
|
Write-Host '[FAIL] .env file not found.'
|
||
|
|
exit 1
|
||
|
|
}
|
||
|
|
|
||
|
|
# Ensure docker daemon is reachable (auto-start + wait + context fix)
|
||
|
|
Ensure-DockerRunning -timeoutSec 180
|
||
|
|
Write-Host '[OK] Docker daemon reachable.'
|
||
|
|
|
||
|
|
# Step 1: Build and start
|
||
|
|
Write-Host '[DOCKER] docker compose up -d --build'
|
||
|
|
& docker compose -f $ComposeFile --env-file $EnvFile up -d --build
|
||
|
|
if ($LASTEXITCODE -ne 0) {
|
||
|
|
Write-Host '[FAIL] docker compose up --build failed.'
|
||
|
|
exit 1
|
||
|
|
}
|
||
|
|
Write-Host '[DOCKER] UP'
|
||
|
|
Write-Host ''
|
||
|
|
|
||
|
|
# Step 2: Wait for /health 200
|
||
|
|
$base = $BaseUrl.TrimEnd('/')
|
||
|
|
$healthUrl = $base + '/health'
|
||
|
|
Write-Host ('[WAIT] Waiting for ' + $healthUrl + ' (max ' + $WaitSeconds + 's)...')
|
||
|
|
|
||
|
|
$healthy = $false
|
||
|
|
for ($i = 0; $i -lt $WaitSeconds; $i++) {
|
||
|
|
try {
|
||
|
|
$resp = Invoke-WebRequest -Method GET -Uri $healthUrl -TimeoutSec 5 -UseBasicParsing
|
||
|
|
if ([int]$resp.StatusCode -eq 200) {
|
||
|
|
$healthy = $true
|
||
|
|
break
|
||
|
|
}
|
||
|
|
} catch {
|
||
|
|
# Not ready yet
|
||
|
|
}
|
||
|
|
Start-Sleep -Seconds 1
|
||
|
|
if (($i % 10) -eq 9) {
|
||
|
|
Write-Host (' ... ' + ($i + 1) + 's elapsed')
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (-not $healthy) {
|
||
|
|
Write-Host ''
|
||
|
|
Write-Host '[WAIT] TIMEOUT - backend did not become healthy.'
|
||
|
|
Write-Host ''
|
||
|
|
Write-Host 'Container logs (last 80 lines):'
|
||
|
|
try { & docker compose -f $ComposeFile logs --tail 80 } catch { }
|
||
|
|
Write-Host ''
|
||
|
|
Write-Host 'Hint: containers are still running so you can inspect logs:'
|
||
|
|
Write-Host (' docker compose -f "' + $ComposeFile + '" logs --follow')
|
||
|
|
Write-Host (' docker compose -f "' + $ComposeFile + '" down')
|
||
|
|
Write-Host ''
|
||
|
|
Write-Host '[RESULT] FAIL'
|
||
|
|
exit 1
|
||
|
|
}
|
||
|
|
|
||
|
|
Write-Host '[WAIT] HEALTH OK'
|
||
|
|
Write-Host ''
|
||
|
|
|
||
|
|
# Step 3: Run smoke suite
|
||
|
|
if (-not (Test-Path -LiteralPath $SmokeScript)) {
|
||
|
|
Write-Host '[FAIL] smoke_suite.ps1 not found.'
|
||
|
|
exit 1
|
||
|
|
}
|
||
|
|
|
||
|
|
Write-Host '[SMOKE] Running smoke_suite.ps1 against docker...'
|
||
|
|
& powershell -ExecutionPolicy Bypass -File $SmokeScript -BaseUrl $base -EnvFile $EnvFile
|
||
|
|
$smokeExit = $LASTEXITCODE
|
||
|
|
Write-Host ''
|
||
|
|
|
||
|
|
# Optional: stop containers
|
||
|
|
if ($DownAfter) {
|
||
|
|
Write-Host '[DOCKER] DownAfter set - stopping containers...'
|
||
|
|
try { & docker compose -f $ComposeFile down } catch { }
|
||
|
|
Write-Host '[DOCKER] DOWN'
|
||
|
|
Write-Host ''
|
||
|
|
}
|
||
|
|
|
||
|
|
if ($smokeExit -ne 0) {
|
||
|
|
Write-Host '[SMOKE] FAIL'
|
||
|
|
if (-not $DownAfter) {
|
||
|
|
Write-Host ''
|
||
|
|
Write-Host 'Hint: containers are still running for inspection:'
|
||
|
|
Write-Host (' docker compose -f "' + $ComposeFile + '" logs --follow')
|
||
|
|
Write-Host (' docker compose -f "' + $ComposeFile + '" down')
|
||
|
|
}
|
||
|
|
Write-Host ''
|
||
|
|
Write-Host '[RESULT] FAIL'
|
||
|
|
exit 1
|
||
|
|
}
|
||
|
|
|
||
|
|
Write-Host '[SMOKE] PASS'
|
||
|
|
Write-Host ''
|
||
|
|
Write-Host '[RESULT] PASS - Step 14 Docker/Compose smoke test complete.'
|
||
|
|
exit 0
|