Sync all scripts from website downloads — 352 scripts total
Includes updated JS challenge scripts with Claude-User whitelist, same-site referer bypass, Blackbox-Exporter allowed bot, and all new exporters, cheat sheets, and automation scripts.
This commit is contained in:
@@ -0,0 +1,637 @@
|
||||
###############################################################################
|
||||
#### windows-container-smoke-tests.ps1 — Verify Windows container health ####
|
||||
#### Checks Docker/containerd service, container lifecycle, isolation ####
|
||||
#### modes, NAT networking, port mapping, volumes, and event logs. ####
|
||||
#### ####
|
||||
#### Author: Phil Connor ####
|
||||
#### Contact: contact@mylinux.work ####
|
||||
#### License: MIT ####
|
||||
#### Version: 1.0 ####
|
||||
#### ####
|
||||
#### Usage: .\windows-container-smoke-tests.ps1 ####
|
||||
#### .\windows-container-smoke-tests.ps1 -ContainerRuntime docker ####
|
||||
#### .\windows-container-smoke-tests.ps1 -OutputFormat tap ####
|
||||
#### ####
|
||||
#### See -Help for all options. ####
|
||||
###############################################################################
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[ValidateSet("docker","containerd")]
|
||||
[string]$ContainerRuntime = "docker",
|
||||
[string]$TestImage = "mcr.microsoft.com/windows/nanoserver:ltsc2022",
|
||||
[ValidateSet("text","tap")]
|
||||
[string]$OutputFormat = "text",
|
||||
[switch]$NoColor,
|
||||
[switch]$Help
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Continue"
|
||||
|
||||
# ============================================================================
|
||||
# HELP
|
||||
# ============================================================================
|
||||
|
||||
if ($Help) {
|
||||
@"
|
||||
Usage: .\windows-container-smoke-tests.ps1 [OPTIONS]
|
||||
|
||||
Smoke-test Windows container infrastructure. PowerShell 5.1+.
|
||||
Designed for Windows Server or Windows 10/11 with containers enabled.
|
||||
|
||||
Parameters:
|
||||
-ContainerRuntime RT Container runtime: docker (default), containerd
|
||||
-TestImage IMAGE Test image (default: mcr.microsoft.com/windows/nanoserver:ltsc2022)
|
||||
-OutputFormat FORMAT Output: text (default), tap
|
||||
-NoColor Disable coloured output
|
||||
-Verbose Show debug output
|
||||
-Help Show this help
|
||||
|
||||
Examples:
|
||||
.\windows-container-smoke-tests.ps1
|
||||
.\windows-container-smoke-tests.ps1 -ContainerRuntime containerd
|
||||
.\windows-container-smoke-tests.ps1 -TestImage mcr.microsoft.com/windows/servercore:ltsc2022
|
||||
.\windows-container-smoke-tests.ps1 -OutputFormat tap -NoColor
|
||||
"@
|
||||
exit 0
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# STATE
|
||||
# ============================================================================
|
||||
|
||||
$script:Pass = 0
|
||||
$script:Fail = 0
|
||||
$script:Skip = 0
|
||||
$script:Total = 0
|
||||
$script:Results = @()
|
||||
$script:StartTime = Get-Date
|
||||
|
||||
# ============================================================================
|
||||
# COLORS
|
||||
# ============================================================================
|
||||
|
||||
function Write-Color {
|
||||
param([string]$Text, [string]$Color = "White")
|
||||
if ($NoColor) {
|
||||
Write-Host $Text
|
||||
} else {
|
||||
Write-Host $Text -ForegroundColor $Color
|
||||
}
|
||||
}
|
||||
|
||||
function Write-Log { param([string]$Msg) Write-Color "[INFO] $Msg" "Cyan" }
|
||||
function Write-Warn { param([string]$Msg) Write-Color "[WARN] $Msg" "Yellow" }
|
||||
function Write-Err { param([string]$Msg) Write-Color "[ERROR] $Msg" "Red" }
|
||||
|
||||
# ============================================================================
|
||||
# TEST RESULT RECORDING
|
||||
# ============================================================================
|
||||
|
||||
function Record-Pass {
|
||||
param([string]$Name, [string]$Detail = "")
|
||||
$script:Pass++
|
||||
$script:Total++
|
||||
$script:Results += [PSCustomObject]@{ Status="PASS"; Name=$Name; Detail=$Detail }
|
||||
if ($OutputFormat -eq "tap") {
|
||||
Write-Host "ok $($script:Total) - $Name$(if($Detail){" ($Detail)"})"
|
||||
} else {
|
||||
$mark = if ($NoColor) { "[PASS]" } else { [char]0x2713 }
|
||||
$msg = " $mark $Name"
|
||||
if ($Detail) { $msg += " - $Detail" }
|
||||
Write-Color $msg "Green"
|
||||
}
|
||||
}
|
||||
|
||||
function Record-Fail {
|
||||
param([string]$Name, [string]$Detail = "")
|
||||
$script:Fail++
|
||||
$script:Total++
|
||||
$script:Results += [PSCustomObject]@{ Status="FAIL"; Name=$Name; Detail=$Detail }
|
||||
if ($OutputFormat -eq "tap") {
|
||||
Write-Host "not ok $($script:Total) - $Name"
|
||||
if ($Detail) { Write-Host " # $Detail" }
|
||||
} else {
|
||||
$mark = if ($NoColor) { "[FAIL]" } else { [char]0x2717 }
|
||||
$msg = " $mark $Name"
|
||||
if ($Detail) { $msg += " - $Detail" }
|
||||
Write-Color $msg "Red"
|
||||
}
|
||||
}
|
||||
|
||||
function Record-Skip {
|
||||
param([string]$Name, [string]$Reason = "")
|
||||
$script:Skip++
|
||||
$script:Total++
|
||||
$script:Results += [PSCustomObject]@{ Status="SKIP"; Name=$Name; Detail=$Reason }
|
||||
if ($OutputFormat -eq "tap") {
|
||||
Write-Host "ok $($script:Total) - $Name # SKIP $Reason"
|
||||
} else {
|
||||
$mark = if ($NoColor) { "[SKIP]" } else { [char]0x2298 }
|
||||
$msg = " $mark $Name"
|
||||
if ($Reason) { $msg += " - $Reason" }
|
||||
Write-Color $msg "Yellow"
|
||||
}
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# HELPERS
|
||||
# ============================================================================
|
||||
|
||||
function Test-CommandExists {
|
||||
param([string]$Command)
|
||||
$null -ne (Get-Command $Command -ErrorAction SilentlyContinue)
|
||||
}
|
||||
|
||||
function Write-Section {
|
||||
param([string]$Name)
|
||||
if ($OutputFormat -eq "text") {
|
||||
Write-Host ""
|
||||
Write-Color $Name "White"
|
||||
}
|
||||
}
|
||||
|
||||
function Remove-TestContainer {
|
||||
param([string]$Name)
|
||||
try { docker rm -f $Name 2>&1 | Out-Null } catch {}
|
||||
}
|
||||
|
||||
function Test-DockerReady {
|
||||
param([string]$TestName, [switch]$NeedImage)
|
||||
if (-not (Test-CommandExists "docker")) {
|
||||
Record-Skip $TestName "docker command not found"; return $false
|
||||
}
|
||||
if ($NeedImage -and -not $script:ImageAvailable) {
|
||||
Record-Skip $TestName "test image not available"; return $false
|
||||
}
|
||||
return $true
|
||||
}
|
||||
|
||||
$script:ImageAvailable = $false
|
||||
$script:TestContainerPrefix = "smoketest-container"
|
||||
|
||||
# ============================================================================
|
||||
# TESTS
|
||||
# ============================================================================
|
||||
|
||||
# -- 1. Container Service Running -------------------------------------------
|
||||
|
||||
function Test-ContainerService {
|
||||
Write-Section "Service"
|
||||
|
||||
$serviceName = if ($ContainerRuntime -eq "containerd") { "containerd" } else { "docker" }
|
||||
|
||||
try {
|
||||
$svc = Get-Service -Name $serviceName -ErrorAction Stop
|
||||
if ($svc.Status -eq "Running") {
|
||||
Record-Pass "Container service running" "$serviceName ($($svc.Status))"
|
||||
} else {
|
||||
Record-Fail "Container service running" "$serviceName is $($svc.Status)"
|
||||
}
|
||||
} catch {
|
||||
Record-Fail "Container service running" "$serviceName service not found"
|
||||
}
|
||||
}
|
||||
|
||||
# -- 2. Daemon Responding ---------------------------------------------------
|
||||
|
||||
function Test-DaemonHealth {
|
||||
if ($ContainerRuntime -eq "containerd") {
|
||||
if (Test-CommandExists "ctr") {
|
||||
try {
|
||||
$output = ctr version 2>&1 | Out-String
|
||||
if ($output -match "Version:" -or $output -match "Revision:") {
|
||||
Record-Pass "Daemon responding" "containerd responding"
|
||||
} else {
|
||||
Record-Fail "Daemon responding" "ctr version returned unexpected output"
|
||||
}
|
||||
} catch {
|
||||
Record-Fail "Daemon responding" "ctr error - $($_.Exception.Message)"
|
||||
}
|
||||
} else {
|
||||
Record-Fail "Daemon responding" "ctr command not found"
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if (-not (Test-CommandExists "docker")) {
|
||||
Record-Fail "Daemon responding" "docker command not found"
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
$output = docker info --format '{{.ServerVersion}}' 2>&1 | Out-String
|
||||
if ($LASTEXITCODE -eq 0 -and $output -match "\d+\.\d+") {
|
||||
Record-Pass "Daemon responding" "Docker Engine v$($output.Trim())"
|
||||
} else {
|
||||
Record-Fail "Daemon responding" "Docker daemon not responding"
|
||||
}
|
||||
} catch {
|
||||
Record-Fail "Daemon responding" "docker error - $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
|
||||
# -- 3. Container Runtime Mode ----------------------------------------------
|
||||
|
||||
function Test-RuntimeMode {
|
||||
Write-Section "Runtime"
|
||||
|
||||
if ($ContainerRuntime -eq "containerd") {
|
||||
Record-Skip "Container runtime mode" "mode detection not applicable to containerd"
|
||||
return
|
||||
}
|
||||
if (-not (Test-DockerReady "Container runtime mode")) { return }
|
||||
|
||||
try {
|
||||
$info = docker info 2>&1 | Out-String
|
||||
if ($info -match "OSType:\s*windows") {
|
||||
Record-Pass "Container runtime mode" "Windows containers"
|
||||
} elseif ($info -match "OSType:\s*linux") {
|
||||
Record-Fail "Container runtime mode" "Linux containers mode - switch to Windows containers"
|
||||
} else {
|
||||
Record-Fail "Container runtime mode" "unable to determine container mode"
|
||||
}
|
||||
} catch {
|
||||
Record-Fail "Container runtime mode" "docker info error - $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
|
||||
# -- 4. Image Pull -----------------------------------------------------------
|
||||
|
||||
function Test-ImagePull {
|
||||
Write-Section "Images"
|
||||
|
||||
if (-not (Test-DockerReady "Image pull")) { return }
|
||||
|
||||
try {
|
||||
# Check if image already exists locally
|
||||
$existing = docker images --format '{{.Repository}}:{{.Tag}}' 2>&1 | Out-String
|
||||
if ($existing -match [regex]::Escape($TestImage)) {
|
||||
$script:ImageAvailable = $true
|
||||
Record-Pass "Image pull" "$TestImage (already present)"
|
||||
return
|
||||
}
|
||||
|
||||
# Attempt pull
|
||||
$pullOutput = docker pull $TestImage 2>&1 | Out-String
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
$script:ImageAvailable = $true
|
||||
Record-Pass "Image pull" $TestImage
|
||||
} elseif ($pullOutput -match "timeout|network|unreachable|no match") {
|
||||
Record-Skip "Image pull" "network unavailable or image not found"
|
||||
} else {
|
||||
Record-Fail "Image pull" "pull failed - $($pullOutput.Trim())"
|
||||
}
|
||||
} catch {
|
||||
Record-Skip "Image pull" "pull error - $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
|
||||
# -- 5. Container Lifecycle --------------------------------------------------
|
||||
|
||||
function Test-ContainerLifecycle {
|
||||
Write-Section "Lifecycle"
|
||||
|
||||
if (-not (Test-DockerReady "Container lifecycle" -NeedImage)) { return }
|
||||
|
||||
$name = "$($script:TestContainerPrefix)-lifecycle"
|
||||
Remove-TestContainer $name
|
||||
|
||||
try {
|
||||
# Create
|
||||
docker create --name $name $TestImage cmd /c "echo smoketest" 2>&1 | Out-Null
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Record-Fail "Container lifecycle" "create failed"
|
||||
Remove-TestContainer $name
|
||||
return
|
||||
}
|
||||
docker start $name 2>&1 | Out-Null
|
||||
Start-Sleep -Seconds 2
|
||||
docker stop $name -t 5 2>&1 | Out-Null
|
||||
docker rm $name 2>&1 | Out-Null
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Record-Pass "Container lifecycle" "create, start, stop, remove"
|
||||
} else {
|
||||
Record-Fail "Container lifecycle" "remove failed"
|
||||
}
|
||||
} catch {
|
||||
Record-Fail "Container lifecycle" $_.Exception.Message
|
||||
Remove-TestContainer $name
|
||||
}
|
||||
}
|
||||
|
||||
# -- 6. Process Isolation Mode -----------------------------------------------
|
||||
|
||||
function Test-ProcessIsolation {
|
||||
Write-Section "Isolation"
|
||||
|
||||
if (-not (Test-DockerReady "Process isolation mode" -NeedImage)) { return }
|
||||
|
||||
$name = "$($script:TestContainerPrefix)-process"
|
||||
Remove-TestContainer $name
|
||||
try {
|
||||
$output = docker run --rm --isolation=process --name $name $TestImage cmd /c "echo process-ok" 2>&1 | Out-String
|
||||
if ($LASTEXITCODE -eq 0 -and $output -match "process-ok") {
|
||||
Record-Pass "Process isolation mode" "process isolation available"
|
||||
} elseif ($output -match "not supported|not available|HCS") {
|
||||
Record-Skip "Process isolation mode" "not supported on this host (requires Windows Server)"
|
||||
} else {
|
||||
Record-Fail "Process isolation mode" "unexpected result - $($output.Trim())"
|
||||
}
|
||||
} catch {
|
||||
Record-Fail "Process isolation mode" $_.Exception.Message
|
||||
} finally {
|
||||
Remove-TestContainer $name
|
||||
}
|
||||
}
|
||||
|
||||
# -- 7. Hyper-V Isolation Mode -----------------------------------------------
|
||||
|
||||
function Test-HyperVIsolation {
|
||||
if (-not (Test-DockerReady "Hyper-V isolation mode" -NeedImage)) { return }
|
||||
|
||||
# Check if Hyper-V is installed (client vs server detection)
|
||||
$hypervEnabled = $false
|
||||
try {
|
||||
$hyperv = Get-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -ErrorAction Stop
|
||||
$hypervEnabled = ($hyperv.State -eq "Enabled")
|
||||
} catch {
|
||||
try {
|
||||
$hypervRole = Get-WindowsFeature -Name Hyper-V -ErrorAction Stop
|
||||
$hypervEnabled = $hypervRole.Installed
|
||||
} catch {}
|
||||
}
|
||||
if (-not $hypervEnabled) {
|
||||
Record-Skip "Hyper-V isolation mode" "Hyper-V not installed"
|
||||
return
|
||||
}
|
||||
|
||||
$name = "$($script:TestContainerPrefix)-hyperv"
|
||||
Remove-TestContainer $name
|
||||
try {
|
||||
$output = docker run --rm --isolation=hyperv --name $name $TestImage cmd /c "echo hyperv-ok" 2>&1 | Out-String
|
||||
if ($LASTEXITCODE -eq 0 -and $output -match "hyperv-ok") {
|
||||
Record-Pass "Hyper-V isolation mode" "Hyper-V isolation available"
|
||||
} elseif ($output -match "not supported|not available|HCS") {
|
||||
Record-Skip "Hyper-V isolation mode" "Hyper-V isolation not available"
|
||||
} else {
|
||||
Record-Fail "Hyper-V isolation mode" "unexpected result - $($output.Trim())"
|
||||
}
|
||||
} catch {
|
||||
Record-Fail "Hyper-V isolation mode" $_.Exception.Message
|
||||
} finally {
|
||||
Remove-TestContainer $name
|
||||
}
|
||||
}
|
||||
|
||||
# -- 8. NAT Network Exists ---------------------------------------------------
|
||||
|
||||
function Test-NATNetwork {
|
||||
Write-Section "Networking"
|
||||
|
||||
if (-not (Test-DockerReady "NAT network exists")) { return }
|
||||
|
||||
try {
|
||||
$networks = docker network ls --format '{{.Name}}' 2>&1 | Out-String
|
||||
if ($networks -match "(?m)^nat$") {
|
||||
Record-Pass "NAT network exists" "default nat network present"
|
||||
} else {
|
||||
Record-Fail "NAT network exists" "nat network not found"
|
||||
}
|
||||
} catch {
|
||||
Record-Fail "NAT network exists" $_.Exception.Message
|
||||
}
|
||||
}
|
||||
|
||||
# -- 9. Outbound Connectivity -----------------------------------------------
|
||||
|
||||
function Test-OutboundConnectivity {
|
||||
if (-not (Test-DockerReady "Container outbound connectivity" -NeedImage)) { return }
|
||||
|
||||
$name = "$($script:TestContainerPrefix)-outbound"
|
||||
Remove-TestContainer $name
|
||||
try {
|
||||
$output = docker run --rm --name $name $TestImage cmd /c "ping -n 1 8.8.8.8" 2>&1 | Out-String
|
||||
if ($LASTEXITCODE -eq 0 -and $output -match "Reply from|bytes=") {
|
||||
Record-Pass "Container outbound connectivity" "ping to 8.8.8.8 succeeded"
|
||||
} elseif ($output -match "timed out|unreachable|could not find|General failure") {
|
||||
Record-Fail "Container outbound connectivity" "no outbound connectivity"
|
||||
} else {
|
||||
Record-Fail "Container outbound connectivity" "exit code $LASTEXITCODE"
|
||||
}
|
||||
} catch {
|
||||
Record-Fail "Container outbound connectivity" $_.Exception.Message
|
||||
} finally {
|
||||
Remove-TestContainer $name
|
||||
}
|
||||
}
|
||||
|
||||
# -- 10. Port Mapping --------------------------------------------------------
|
||||
|
||||
function Test-PortMapping {
|
||||
if (-not (Test-DockerReady "Port mapping" -NeedImage)) { return }
|
||||
|
||||
$name = "$($script:TestContainerPrefix)-portmap"
|
||||
$hostPort = 48199
|
||||
Remove-TestContainer $name
|
||||
try {
|
||||
docker run -d --rm --name $name -p "${hostPort}:80" $TestImage cmd /c "ping -n 30 127.0.0.1 >nul" 2>&1 | Out-Null
|
||||
Start-Sleep -Seconds 3
|
||||
|
||||
$state = docker inspect --format '{{.State.Running}}' $name 2>&1 | Out-String
|
||||
if ($state.Trim() -eq "true") {
|
||||
$portInfo = docker port $name 2>&1 | Out-String
|
||||
if ($portInfo -match "$hostPort" -or $portInfo -match "80/tcp") {
|
||||
Record-Pass "Port mapping" "port $hostPort mapped to container"
|
||||
} else {
|
||||
Record-Pass "Port mapping" "container running with port binding"
|
||||
}
|
||||
} else {
|
||||
Record-Fail "Port mapping" "container did not stay running for port test"
|
||||
}
|
||||
} catch {
|
||||
Record-Fail "Port mapping" $_.Exception.Message
|
||||
} finally {
|
||||
Remove-TestContainer $name
|
||||
}
|
||||
}
|
||||
|
||||
# -- 11. Volume Mount --------------------------------------------------------
|
||||
|
||||
function Test-VolumeMount {
|
||||
Write-Section "Storage"
|
||||
|
||||
if (-not (Test-DockerReady "Volume mount" -NeedImage)) { return }
|
||||
|
||||
$name = "$($script:TestContainerPrefix)-volume"
|
||||
$tempDir = Join-Path $env:TEMP "container-smoke-test-vol"
|
||||
Remove-TestContainer $name
|
||||
try {
|
||||
if (Test-Path $tempDir) { Remove-Item $tempDir -Recurse -Force }
|
||||
New-Item -ItemType Directory -Path $tempDir -Force | Out-Null
|
||||
Set-Content -Path (Join-Path $tempDir "testfile.txt") -Value "smoke-test-data"
|
||||
|
||||
$output = docker run --rm --name $name -v "${tempDir}:C:\testmount" $TestImage cmd /c "type C:\testmount\testfile.txt" 2>&1 | Out-String
|
||||
if ($LASTEXITCODE -eq 0 -and $output -match "smoke-test-data") {
|
||||
Record-Pass "Volume mount" "bind mount read successful"
|
||||
} else {
|
||||
Record-Fail "Volume mount" "bind mount failed - $($output.Trim())"
|
||||
}
|
||||
} catch {
|
||||
Record-Fail "Volume mount" $_.Exception.Message
|
||||
} finally {
|
||||
Remove-TestContainer $name
|
||||
if (Test-Path $tempDir) { Remove-Item $tempDir -Recurse -Force -ErrorAction SilentlyContinue }
|
||||
}
|
||||
}
|
||||
|
||||
# -- 12. Container Logs ------------------------------------------------------
|
||||
|
||||
function Test-ContainerLogs {
|
||||
Write-Section "Logging"
|
||||
|
||||
if (-not (Test-DockerReady "Container logs" -NeedImage)) { return }
|
||||
|
||||
$name = "$($script:TestContainerPrefix)-logs"
|
||||
Remove-TestContainer $name
|
||||
try {
|
||||
docker run --name $name $TestImage cmd /c "echo log-output-test" 2>&1 | Out-Null
|
||||
Start-Sleep -Seconds 1
|
||||
|
||||
$logs = docker logs $name 2>&1 | Out-String
|
||||
if ($logs -match "log-output-test") {
|
||||
Record-Pass "Container logs" "docker logs returned expected output"
|
||||
} else {
|
||||
Record-Fail "Container logs" "docker logs did not return expected output"
|
||||
}
|
||||
} catch {
|
||||
Record-Fail "Container logs" $_.Exception.Message
|
||||
} finally {
|
||||
Remove-TestContainer $name
|
||||
}
|
||||
}
|
||||
|
||||
# -- 13. Image List ----------------------------------------------------------
|
||||
|
||||
function Test-ImageList {
|
||||
if (-not (Test-DockerReady "Image list")) { return }
|
||||
|
||||
try {
|
||||
$images = docker images --format '{{.Repository}}:{{.Tag}}' 2>&1
|
||||
$imageCount = ($images | Where-Object { $_ -match "\S" -and $_ -notmatch "ERROR" } | Measure-Object).Count
|
||||
if ($imageCount -gt 0) {
|
||||
Record-Pass "Image list" "$imageCount image(s)"
|
||||
} else {
|
||||
Record-Fail "Image list" "no images found"
|
||||
}
|
||||
} catch {
|
||||
Record-Fail "Image list" $_.Exception.Message
|
||||
}
|
||||
}
|
||||
|
||||
# -- 14. Event Log -----------------------------------------------------------
|
||||
|
||||
function Test-EventLog {
|
||||
Write-Section "Event Log"
|
||||
|
||||
try {
|
||||
$containerErrors = @()
|
||||
|
||||
foreach ($logName in @('System', 'Application')) {
|
||||
try {
|
||||
$events = Get-WinEvent -FilterHashtable @{
|
||||
LogName = $logName
|
||||
Level = 2 # Error
|
||||
StartTime = (Get-Date).AddHours(-24)
|
||||
} -ErrorAction Stop | Where-Object {
|
||||
$_.ProviderName -match "docker|container|Hyper-V" -or
|
||||
$_.Message -match "container|docker|containerd"
|
||||
}
|
||||
if ($events) { $containerErrors += $events }
|
||||
} catch [Exception] {
|
||||
if ($_.Exception.Message -notmatch "No events were found") {
|
||||
Write-Verbose "$logName log query error: $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$errorCount = ($containerErrors | Measure-Object).Count
|
||||
if ($errorCount -eq 0) {
|
||||
Record-Pass "Event log" "no container errors in last 24h"
|
||||
} else {
|
||||
$latest = $containerErrors | Sort-Object TimeCreated -Descending | Select-Object -First 1
|
||||
$detail = "$errorCount error(s) in last 24h - latest: $($latest.ProviderName) - $($latest.Message.Substring(0, [Math]::Min(80, $latest.Message.Length)))"
|
||||
Record-Fail "Event log" $detail
|
||||
}
|
||||
} catch {
|
||||
Record-Skip "Event log" "unable to query event logs - $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# OUTPUT
|
||||
# ============================================================================
|
||||
|
||||
function Write-Header {
|
||||
if ($OutputFormat -eq "tap") {
|
||||
Write-Host "TAP version 13"
|
||||
} else {
|
||||
Write-Host ""
|
||||
Write-Color "Windows Container Smoke Tests" "White"
|
||||
Write-Host "Runtime: $ContainerRuntime"
|
||||
Write-Host "Image: $TestImage"
|
||||
Write-Host "Time: $(Get-Date -Format 'yyyy-MM-ddTHH:mm:ssZ')"
|
||||
}
|
||||
}
|
||||
|
||||
function Write-Summary {
|
||||
$duration = [math]::Floor(((Get-Date) - $script:StartTime).TotalSeconds)
|
||||
|
||||
if ($OutputFormat -eq "tap") {
|
||||
Write-Host "1..$($script:Total)"
|
||||
Write-Host "# pass $($script:Pass)"
|
||||
Write-Host "# fail $($script:Fail)"
|
||||
Write-Host "# skip $($script:Skip)"
|
||||
} else {
|
||||
Write-Host ""
|
||||
$separator = [string]::new([char]0x2500, 40)
|
||||
Write-Color $separator "White"
|
||||
Write-Color "Summary $ContainerRuntime ($TestImage)" "White"
|
||||
|
||||
$summaryLine = " $($script:Pass) passed $($script:Fail) failed $($script:Skip) skipped (${duration}s)"
|
||||
Write-Host $summaryLine
|
||||
Write-Color $separator "White"
|
||||
|
||||
if ($script:Fail -eq 0) {
|
||||
Write-Color "All tests passed." "Green"
|
||||
} else {
|
||||
Write-Color "$($script:Fail) test(s) failed." "Red"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# MAIN
|
||||
# ============================================================================
|
||||
|
||||
Write-Header
|
||||
|
||||
# Run all tests
|
||||
Test-ContainerService
|
||||
Test-DaemonHealth
|
||||
Test-RuntimeMode
|
||||
Test-ImagePull
|
||||
Test-ContainerLifecycle
|
||||
Test-ProcessIsolation
|
||||
Test-HyperVIsolation
|
||||
Test-NATNetwork
|
||||
Test-OutboundConnectivity
|
||||
Test-PortMapping
|
||||
Test-VolumeMount
|
||||
Test-ContainerLogs
|
||||
Test-ImageList
|
||||
Test-EventLog
|
||||
|
||||
Write-Summary
|
||||
|
||||
if ($script:Fail -eq 0) { exit 0 } else { exit 1 }
|
||||
Reference in New Issue
Block a user