Files
homelab-gitops/scripts/media-storage-offline.sh
T

79 lines
3.1 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
readonly expected_context="kubernetes-admin@kubernetes"
readonly node="arschrock"
readonly dynmap_ready_label="minecraft.brunner.ninja/dynmap-ready"
readonly library_services=(lidarr.service readarr.service radarr.service sonarr.service bazarr.service)
readonly whisparr_service="whisparr.service"
current_context="$(kubectl config current-context)"
if [[ "${current_context}" != "${expected_context}" ]]; then
echo "Refusing to modify ${node}: context is ${current_context}, expected ${expected_context}." >&2
exit 1
fi
# These host-native library managers must never inspect the empty Btrfs
# directory underneath /komposthaufen when its Bcachefs mount is offline.
sudo -n systemctl stop "${library_services[@]}" "${whisparr_service}"
for service in "${library_services[@]}" "${whisparr_service}"; do
if sudo -n systemctl is-active --quiet "${service}"; then
echo "${service} is still active; do not unmount /komposthaufen." >&2
exit 1
fi
done
kubectl get node "${node}" >/dev/null
if ! kubectl label node "${node}" media.brunner.ninja/multimedia-ready- 2>/dev/null; then
labels=$(kubectl get node "${node}" --output=jsonpath='{.metadata.labels}')
if [[ "${labels}" == *"media.brunner.ninja/multimedia-ready"* ]]; then
echo "Could not remove the media-ready label from ${node}; do not unmount." >&2
exit 1
fi
fi
for namespace in plex jellyfin copyparty; do
scheduled_pods=$(kubectl --namespace "${namespace}" get pods \
--selector="app.kubernetes.io/component=server" \
--field-selector="spec.nodeName=${node}" \
--output=name)
if [[ -n "${scheduled_pods}" ]]; then
mapfile -t pod_names <<< "${scheduled_pods}"
kubectl --namespace "${namespace}" delete "${pod_names[@]}" --wait=false
for pod in "${pod_names[@]}"; do
kubectl --namespace "${namespace}" wait --for=delete "${pod}" --timeout=5m
done
fi
done
if ! kubectl label node "${node}" "${dynmap_ready_label}-" 2>/dev/null; then
labels=$(kubectl get node "${node}" --output=jsonpath='{.metadata.labels}')
if [[ "${labels}" == *"${dynmap_ready_label}"* ]]; then
echo "Could not remove the Dynmap-ready label from ${node}; do not unmount." >&2
exit 1
fi
fi
mapfile -t paper_pods < <(kubectl --namespace mcserver get pods \
--selector="app.kubernetes.io/name=minecraft-paper,app.kubernetes.io/instance=paper" \
--field-selector="spec.nodeName=${node}" --output=name)
if ((${#paper_pods[@]})); then
kubectl --namespace mcserver delete "${paper_pods[@]}" --wait=false
for pod in "${paper_pods[@]}"; do
kubectl --namespace mcserver wait --for=delete "${pod}" --timeout=15m
done
fi
for namespace in plex jellyfin copyparty; do
remaining_pods=$(kubectl --namespace "${namespace}" get pods \
--selector="app.kubernetes.io/component=server" \
--field-selector="spec.nodeName=${node}" \
--output=name)
if [[ -n "${remaining_pods}" ]]; then
echo "A ${namespace} Pod is still assigned to ${node}; do not unmount." >&2
exit 1
fi
done
echo "Plex, Jellyfin, Copyparty and Paper are stopped on ${node}. Replacements stay Pending until their storage-ready labels return."