sodew-bash
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
# Waits for the k3s API to become ready by polling /readyz.
|
||||
# Retries up to $k3sReadyRetries times with $k3sReadySleep seconds between attempts.
|
||||
function k3sReady() {
|
||||
local tries=${k3sReadyRetries:-10}
|
||||
local delay=${k3sReadySleep:-2}
|
||||
local i
|
||||
for ((i=1; i<=tries; i++)); do
|
||||
"$k3sCmd" kubectl get --raw=/readyz >/dev/null 2>&1 && return 0
|
||||
sleep "$delay"
|
||||
done
|
||||
|
||||
appError "k3s API not ready after $tries tries"
|
||||
return 1
|
||||
}
|
||||
|
||||
# Validates a YAML file against the Kubernetes API (dry-run).
|
||||
# $1 (file): path to the YAML file.
|
||||
function k3sYamlCheck() {
|
||||
local file="$1"
|
||||
[[ -n "$file" ]] || { appError "File not specified"; return 1; }
|
||||
[[ -f "$file" ]] || { appError "File not found: $file"; return 1; }
|
||||
|
||||
k3sReady
|
||||
runFail "$k3sCmd" kubectl apply --dry-run=client -f "$file"
|
||||
}
|
||||
|
||||
# Applies a YAML configuration to Kubernetes.
|
||||
# $1 (file): path to the YAML configuration file.
|
||||
function k3sYamlApply() {
|
||||
local file="$1" output error
|
||||
[[ -n "$file" ]] || { appError "File not specified"; return 1; }
|
||||
|
||||
run output error "$k3sCmd" kubectl apply -f "$file" --validate=false --request-timeout=60s || {
|
||||
appError "Error applying YAML: ${error:-$output}"
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
# Runs kubectl in $k3sNamespace after ensuring k3s is ready.
|
||||
function k3sRun() {
|
||||
k3sReady || return 1
|
||||
"$k3sCmd" kubectl -n "$k3sNamespace" "$@"
|
||||
}
|
||||
|
||||
# Lists pod names sorted alphabetically, optionally filtered by app label.
|
||||
# [$1] (app): app label value to filter by (optional).
|
||||
function k3sPodList() {
|
||||
local args=()
|
||||
[[ -n "${1-}" ]] && args+=(-l "app=$1")
|
||||
|
||||
k3sRun get pods "${args[@]}" -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' --sort-by='{.metadata.name}'
|
||||
}
|
||||
|
||||
# Lists pods with detailed status: name|status|phase|reason.
|
||||
# status is 1 when the pod is fully ready (phase Running/Succeeded), 0 otherwise.
|
||||
# phase/reason describe the state for humans — a fine pod (status=1) can still show
|
||||
# different phase/reason combinations, so gate logic must use status, not phase.
|
||||
# reason is a comma-separated, deduplicated list of not-True condition types (excluding
|
||||
# the generic PodReadyToStartContainers/Initialized/ContainersReady/Ready chain, which
|
||||
# is always false together during startup and adds nothing beyond phase) plus each
|
||||
# not-ready container's (including init containers) waiting/terminated reason
|
||||
# (CrashLoopBackOff, ImagePullBackOff, OOMKilled, PodInitializing, ...).
|
||||
# [$1] (app): app label value to filter by (optional).
|
||||
function k3sPodListStatus() {
|
||||
local args=()
|
||||
[[ -n "${1-}" ]] && args+=(-l "app=$1")
|
||||
|
||||
k3sRun get pods "${args[@]}" -o json --sort-by='{.metadata.name}' | jq -r '
|
||||
def dedupe: reduce .[] as $x ([]; if any(.[]; . == $x) then . else . + [$x] end);
|
||||
|
||||
.items[] |
|
||||
(.metadata.name) as $name |
|
||||
(.status.phase // "Unknown") as $phaseRaw |
|
||||
(.status.conditions // []) as $conditions |
|
||||
([$conditions[] | select(.type == "Ready")][0]) as $ready |
|
||||
([$conditions[] | select(.type == "DisruptionTarget")][0]) as $disruption |
|
||||
((.status.initContainerStatuses // []) + (.status.containerStatuses // [])) as $containers |
|
||||
(["PodReadyToStartContainers", "Initialized", "ContainersReady", "Ready"]) as $noisyConditionTypes |
|
||||
|
||||
(
|
||||
if $phaseRaw == "Running" and ($disruption.status // "") == "True" then "Terminating"
|
||||
elif $phaseRaw == "Running" and ($ready.status // "False") != "True" then "NotReady"
|
||||
else $phaseRaw
|
||||
end
|
||||
) as $phase |
|
||||
|
||||
(if $phase == "Running" or $phase == "Succeeded" then 1 else 0 end) as $status |
|
||||
|
||||
(
|
||||
[$conditions[] |
|
||||
(if .type == "DisruptionTarget" then (select(.status == "True")) else (select(.status != "True")) end) |
|
||||
select(.type as $t | $noisyConditionTypes | index($t) | not) |
|
||||
.type
|
||||
]
|
||||
) as $badConditionTypes |
|
||||
|
||||
(
|
||||
[$containers[] | select(.ready == false) |
|
||||
(.state.waiting.reason // .state.terminated.reason) | select(. != null)
|
||||
]
|
||||
) as $containerReasons |
|
||||
|
||||
((if $status == 1 then [] else ($badConditionTypes + $containerReasons | dedupe) end) | join(",")) as $reason |
|
||||
|
||||
"\($name)|\($status)|\($phase)|\($reason)"
|
||||
'
|
||||
}
|
||||
|
||||
# Captures the current list of pod names into an array variable.
|
||||
# $1 (varname): name of the array variable to populate.
|
||||
function k3sPodsSnapshot() {
|
||||
local -n __out="$1"
|
||||
mapfile -t __out < <(
|
||||
k3sRun get pods --no-headers 2>/dev/null | awk '{print $1}'
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user