# Frey's servers: which one is on, which exist, and switching between them. # # .\tools\server.ps1 status # which server is on, and is it up # .\tools\server.ps1 list # every server in this repo # .\tools\server.ps1 switch terror # turn "terror" on (and the current one off) # # Run from the repo root. Only one server runs at a time; switching stops the # current one (its world is kept) and starts the other at the same address, # valls.dev. Written for Windows PowerShell 5.1: no &&, and the patch goes # through a file because 5.1 mangles JSON quotes passed to kubectl. param( [Parameter(Position = 0)][ValidateSet("status", "list", "switch")][string]$Command = "status", [Parameter(Position = 1)][string]$Name ) # Not "Stop": on 5.1 that turns any stderr line from git/kubectl into a # terminating error. Failures are checked through $LASTEXITCODE instead. $ns = "game-servers" function Get-ActiveServer { $json = kubectl -n $ns get statefulset minecraft -o json | Out-String if ($LASTEXITCODE -ne 0) { throw "kubectl could not read the server" } return ($json | ConvertFrom-Json).spec.template.metadata.annotations.'valls.dev/server' } $root = Split-Path -Parent $PSScriptRoot switch ($Command) { "status" { $active = Get-ActiveServer Write-Output "Server on now: $active" kubectl -n $ns get pod minecraft-0 } "list" { $active = Get-ActiveServer Get-ChildItem (Join-Path $root "servers") -Directory | ForEach-Object { $envFile = Join-Path $_.FullName "server.env" if (Test-Path $envFile) { $v = (Select-String -Path $envFile -Pattern '^(TYPE|VERSION)=(.*)$' | ForEach-Object { $_.Matches[0].Groups[2].Value }) -join " " $mark = if ($_.Name -eq $active) { " <- on now" } else { "" } Write-Output ("{0,-20} {1}{2}" -f $_.Name, $v, $mark) } } } "switch" { if (-not $Name) { throw "Say which server: .\tools\server.ps1 switch " } if ($Name -notmatch '^[a-z0-9][a-z0-9-]{0,39}$') { throw "Server names are lowercase letters, digits and dashes only" } # The server reads its definition from what has been pushed, not from this # folder, so refuse to switch to something that only exists locally. git -C $root fetch -q origin git -C $root cat-file -e "origin/main:servers/$Name/server.env" 2>$null if ($LASTEXITCODE -ne 0) { throw "servers/$Name/server.env is not pushed yet: commit and push it first" } $active = Get-ActiveServer if ($active -eq $Name) { Write-Output "$Name is already on."; return } $patch = Join-Path $env:TEMP "minecraft-switch.json" Set-Content -Path $patch -Encoding ASCII -Value ('{"spec":{"template":{"metadata":{"annotations":{"valls.dev/server":"' + $Name + '"}}}}}') kubectl -n $ns patch statefulset minecraft --type merge --patch-file $patch if ($LASTEXITCODE -ne 0) { throw "kubectl could not switch the server" } Write-Output "Switching $active -> $Name. Waiting for it to start (a brand-new server can take up to 15 minutes)..." kubectl -n $ns rollout status statefulset/minecraft --timeout=16m if ($LASTEXITCODE -ne 0) { throw "It did not start. Look at: kubectl -n $ns logs minecraft-0 -c minecraft --tail=100" } Write-Output "$Name is on." } }