You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

68 lines
2.5 KiB
PowerShell

$hetznerCredentials = Get-Credential
$nodeList = docker node ls --format '{{json .}}'| ConvertFrom-Json | ForEach-Object {
docker node inspect $_.ID | ConvertFrom-Json
}
$onlineNodeList = $nodeList | Where-Object {$_.Spec.Availability -eq 'active'}
if (!($nodeList | Where-Object {$_.Spec.Availability -ne 'active'})) {
Write-Output 'all hosts online, nothing to failover'
exit
}
$failoverAddressList = (Invoke-RestMethod -Uri 'https://robot-ws.your-server.de/failover' -Authentication Basic -Credential $hetznerCredentials).failover
$onlineNodeAddressList = $onlineNodeList.Description.Hostname | ForEach-Object {
dig +short $_
}
$offlineAddressList = $failoverAddressList | Where-Object active_server_ip -notin $onlineNodeAddressList
$maximumAddressCount = [Math]::Ceiling($failoverAddressList.Count / $onlineNodeList.Count)
$i = 0
$addressGroupList = $onlineNodeAddressList
| ForEach-Object {
$nodeAddress = $_
@{
Count = [int]($addressGroupList | Where-Object {$_.Name -eq $nodeAddress}).Count
NodeAddress = $nodeAddress
}
}
| Sort-Object Count
$distributionTarget = :distribution foreach ($addressGroup in $addressGroupList) {
$currentAddressCount = $addressGroup.Count - 1
while ($currentAddressCount -lt $maximumAddressCount) {
if (!$offlineAddressList[$i]) {
# abort when all addresses are assigned
break distribution
}
@{
active_server_ip = $addressGroup.NodeAddress
ip = $offlineAddressList[$i++].ip
node = (dig +short -x $($addressGroup.NodeAddress)) -replace '\.$'
}
$currentAddressCount++
}
}
# docker label updates must not run in parallel to prevent out-of-sequence errors
$distributionTarget | ForEach-Object {
# first add the new labels and afterwards remove the old ones
# this prevents situations where no host has the label anymore
$labelName = 'link.lubi.ip.'+$_.ip
$filter = 'node.label='+$labelName
$cleanupNodeList = docker node ls --filter $filter --format '{{json .}}' | ConvertFrom-Json
$label = $labelName+'=true'
docker node update --label-add $label $($_.node)
$cleanupNodeList | ForEach-Object {
docker node update --label-rm $labelName $($_.ID)
}
}
$distributionTarget | ForEach-Object -ThrottleLimit $failoverAddressList.Count -Parallel {
Invoke-RestMethod -Method Post -Uri ('https://robot-ws.your-server.de/failover/{0}' -f $_.ip) -Authentication Basic -Credential $using:hetznerCredentials -Body @{active_server_ip=$_.active_server_ip}
}