97 lines
3.2 KiB
PowerShell
97 lines
3.2 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Ensures the branch-isolated local PostgreSQL databases exist.
|
|
|
|
.DESCRIPTION
|
|
The main and v2 branches have independent migration histories. They must never
|
|
share one schema_migrations row. This helper creates telesrv_main and
|
|
telesrv_v2 in the local Compose PostgreSQL container without modifying or
|
|
deleting the legacy telesrv database.
|
|
|
|
Optional template parameters are intended for a one-time local split when an
|
|
existing database snapshot should be preserved. They are only used when the
|
|
target database does not already exist.
|
|
#>
|
|
[CmdletBinding()]
|
|
param(
|
|
[string]$PostgresContainer = "telesrv-postgres",
|
|
[string]$DbUser = "telesrv",
|
|
[string]$MainTemplate,
|
|
[string]$V2Template
|
|
)
|
|
|
|
Set-StrictMode -Version Latest
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
function Assert-SafeIdentifier {
|
|
param([string]$Name, [string]$Value)
|
|
if ([string]::IsNullOrWhiteSpace($Value) -or $Value -notmatch '^[A-Za-z_][A-Za-z0-9_]*$') {
|
|
throw "$Name must be a PostgreSQL identifier containing only letters, digits, and underscores: '$Value'"
|
|
}
|
|
}
|
|
|
|
function Invoke-Docker {
|
|
param([string[]]$Arguments)
|
|
$oldErrorActionPreference = $ErrorActionPreference
|
|
$ErrorActionPreference = "Continue"
|
|
try {
|
|
$output = & docker @Arguments 2>&1
|
|
$exitCode = $LASTEXITCODE
|
|
} finally {
|
|
$ErrorActionPreference = $oldErrorActionPreference
|
|
}
|
|
$text = ($output | ForEach-Object { $_.ToString() }) -join "`n"
|
|
if ($exitCode -ne 0) {
|
|
throw "docker $($Arguments -join ' ') failed with exit code ${exitCode}:`n$text"
|
|
}
|
|
return $text.Trim()
|
|
}
|
|
|
|
function Test-DatabaseExists {
|
|
param([string]$Database)
|
|
Assert-SafeIdentifier "database" $Database
|
|
$result = Invoke-Docker @(
|
|
"exec", $PostgresContainer,
|
|
"psql", "-U", $DbUser, "-d", "postgres",
|
|
"-v", "ON_ERROR_STOP=1", "-At", "-c",
|
|
"SELECT 1 FROM pg_database WHERE datname = '$Database';"
|
|
)
|
|
return $result -eq "1"
|
|
}
|
|
|
|
function Ensure-Database {
|
|
param([string]$Database, [string]$Template)
|
|
if (Test-DatabaseExists $Database) {
|
|
Write-Host "[ok] PostgreSQL database already exists: $Database"
|
|
return
|
|
}
|
|
|
|
$args = @("exec", $PostgresContainer, "createdb", "-U", $DbUser, "-O", $DbUser)
|
|
if (-not [string]::IsNullOrWhiteSpace($Template)) {
|
|
Assert-SafeIdentifier "template database" $Template
|
|
if (-not (Test-DatabaseExists $Template)) {
|
|
throw "template database does not exist: $Template"
|
|
}
|
|
$args += @("-T", $Template)
|
|
}
|
|
$args += $Database
|
|
Invoke-Docker $args | Out-Null
|
|
$templateSuffix = ""
|
|
if (-not [string]::IsNullOrWhiteSpace($Template)) {
|
|
$templateSuffix = " (template: $Template)"
|
|
}
|
|
Write-Host "[ok] created PostgreSQL database: $Database$templateSuffix"
|
|
}
|
|
|
|
Assert-SafeIdentifier "database user" $DbUser
|
|
if ($PostgresContainer -notmatch '^[A-Za-z0-9_.-]+$') {
|
|
throw "invalid Docker container name: '$PostgresContainer'"
|
|
}
|
|
|
|
$running = Invoke-Docker @("inspect", "-f", "{{.State.Running}}", $PostgresContainer)
|
|
if ($running -ne "true") {
|
|
throw "PostgreSQL container is not running: $PostgresContainer"
|
|
}
|
|
|
|
Ensure-Database "telesrv_main" $MainTemplate
|
|
Ensure-Database "telesrv_v2" $V2Template
|