#!/bin/sh # Read-only node health; patch only the named Factorio Deployment. set -eu node=$(kubectl get node arschrock --ignore-not-found -o json) deployment=$(kubectl -n factorio get deployment factorio -o json) current=$(printf '%s' "$deployment" | jq -c '.spec.template.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[0].matchExpressions[0].values') if [ -z "$node" ]; then mode=odroids else mode=$(printf '%s' "$node" | jq -r ' if .metadata.labels["factorio.brunner.ninja/unavailable"] == "true" or .spec.unschedulable == true then "odroids" else ([.status.conditions[] | select(.type == "Ready")][0]) as $ready | if $ready == null then "hold" elif (now - ($ready.lastTransitionTime | sub("\\.[0-9]+Z$"; "Z") | fromdateiso8601)) < 300 then "hold" elif $ready.status == "True" then "primary" else "odroids" end end') fi case "$mode" in primary) desired='["arschrock"]' ;; odroids) desired='["odroid-h3-00","odroid-h3-01","odroid-h3-02","odroid-h3-03","odroid-h3-04","odroid-h3-05"]' ;; hold) echo 'Node health transition less than five minutes ago; holding placement'; exit 0 ;; *) exit 1 ;; esac if [ "$current" = "$desired" ]; then echo "Placement unchanged: $mode" exit 0 fi # Optimistic concurrency: never overwrite a concurrent deployment or maintenance action. patch=$(printf '%s' "$deployment" | jq -c --argjson nodes "$desired" '[ {op:"test",path:"/metadata/resourceVersion",value:.metadata.resourceVersion}, {op:"replace",path:"/spec/template/spec/affinity/nodeAffinity/requiredDuringSchedulingIgnoredDuringExecution/nodeSelectorTerms/0/matchExpressions/0/values",value:$nodes} ]') kubectl -n factorio patch deployment factorio --type=json -p "$patch" echo "Placement changed to $mode"