150 lines
5.1 KiB
Bash
150 lines
5.1 KiB
Bash
#!/bin/bash
|
|
# Methods library for cert_manager — sourced by run-*.sh and install-cert_manager.sh.
|
|
# SCRIPT_DIR must be set by the caller before sourcing.
|
|
|
|
_kubectl() {
|
|
if command -v kubectl >/dev/null 2>&1; then
|
|
command kubectl "$@"
|
|
elif command -v k0s >/dev/null 2>&1; then
|
|
k0s kubectl "$@"
|
|
else
|
|
echo "ERROR: no kubectl or k0s binary found" >&2; exit 127
|
|
fi
|
|
}
|
|
|
|
_resolve_kubeconfig() {
|
|
if [ -n "${KUBECONFIG:-}" ] && [ -f "$KUBECONFIG" ]; then
|
|
return
|
|
fi
|
|
for candidate in \
|
|
/var/lib/k0s/pki/admin.conf \
|
|
/etc/kubernetes/admin.conf \
|
|
/root/.kube/config; do
|
|
if [ -f "$candidate" ]; then
|
|
export KUBECONFIG="$candidate"
|
|
return
|
|
fi
|
|
done
|
|
if command -v k0s >/dev/null 2>&1; then
|
|
local tmp
|
|
tmp="$(mktemp)"
|
|
k0s kubeconfig admin > "$tmp" 2>/dev/null && export KUBECONFIG="$tmp" && return
|
|
rm -f "$tmp"
|
|
fi
|
|
echo "ERROR: kubeconfig not found — set KUBECONFIG explicitly" >&2; exit 1
|
|
}
|
|
|
|
_require_env() {
|
|
local var="$1"
|
|
if [ -z "${!var:-}" ]; then
|
|
echo "ERROR: required variable $var is not set" >&2; exit 1
|
|
fi
|
|
}
|
|
|
|
_plan_apply() {
|
|
local file="$1"
|
|
local path="$SCRIPT_DIR/manifests/${file}.yaml"
|
|
[ -f "$path" ] || { echo " [skip] ${file}.yaml not in manifests/"; return 0; }
|
|
local content
|
|
content=$(sed '/^\s*#/d; /^\s*$/d' "$path" | tr -d '[:space:]')
|
|
[ -n "$content" ] || { echo " [skip] ${file}.yaml has no content"; return 0; }
|
|
_kubectl apply -f "$path"
|
|
}
|
|
|
|
_plan_apply_skip() {
|
|
local file="$1"
|
|
local path="$SCRIPT_DIR/manifests/${file}.yaml"
|
|
[ -f "$path" ] || { echo " [skip] ${file}.yaml not in manifests/"; return 0; }
|
|
[ -s "$path" ] || { echo " [skip] ${file}.yaml is empty"; return 0; }
|
|
if _kubectl get -f "$path" >/dev/null 2>&1; then
|
|
echo " [skip] $file already exists in cluster"
|
|
return 0
|
|
fi
|
|
_kubectl apply -f "$path"
|
|
}
|
|
|
|
_plan_delete() {
|
|
local file="$1"
|
|
local path="$SCRIPT_DIR/manifests/${file}.yaml"
|
|
[ -f "$path" ] || { echo " [skip] ${file}.yaml not in manifests/"; return 0; }
|
|
[ -s "$path" ] || { echo " [skip] ${file}.yaml is empty"; return 0; }
|
|
_kubectl delete -f "$path" --ignore-not-found
|
|
}
|
|
|
|
_method_apply_bundle() {
|
|
local version="${CERT_MANAGER_VERSION:-v1.19.5}"
|
|
local url="https://github.com/cert-manager/cert-manager/releases/download/${version}/cert-manager.yaml"
|
|
local bundle="${SCRIPT_DIR}/cert-manager.yaml"
|
|
if [ ! -f "$bundle" ]; then
|
|
echo " [apply_bundle] downloading cert-manager ${version}"
|
|
curl -fsSL "$url" -o "$bundle"
|
|
else
|
|
echo " [apply_bundle] bundle already present, skipping download"
|
|
fi
|
|
_kubectl apply --server-side -f "$bundle"
|
|
}
|
|
|
|
# Patch the cert-manager controller deployment to bypass cluster CoreDNS during
|
|
# DNS-01 challenge verification. Without this, _acme-challenge.* lookups can hit
|
|
# split-horizon zone blocks that lack `fallthrough`, returning SERVFAIL and
|
|
# stalling the challenge indefinitely.
|
|
_method_patch_recursive_dns() {
|
|
local ns="${CERT_MANAGER_NAMESPACE:-cert-manager}"
|
|
local ns_csv="${CERT_MANAGER_DNS01_RECURSIVE_NS:-1.1.1.1:53,8.8.8.8:53}"
|
|
local only="${CERT_MANAGER_DNS01_RECURSIVE_ONLY:-true}"
|
|
[ -n "$ns_csv" ] || { echo " [patch_recursive_dns] no nameservers configured, skipping"; return 0; }
|
|
|
|
local args="[\"--dns01-recursive-nameservers=${ns_csv}\""
|
|
if [ "$only" = "true" ] || [ "$only" = "1" ]; then
|
|
args="${args},\"--dns01-recursive-nameservers-only\""
|
|
fi
|
|
args="${args}]"
|
|
|
|
echo " [patch_recursive_dns] dns01 recursive nameservers: ${ns_csv} (only=${only})"
|
|
|
|
local current
|
|
current=$(_kubectl get deployment cert-manager -n "$ns" -o jsonpath='{.spec.template.spec.containers[0].args}' 2>/dev/null || true)
|
|
|
|
local needs_ns_arg=true needs_only_arg=false patched=false
|
|
[[ "$current" == *"--dns01-recursive-nameservers=${ns_csv}"* ]] && needs_ns_arg=false
|
|
if [ "$only" = "true" ] || [ "$only" = "1" ]; then
|
|
[[ "$current" != *"--dns01-recursive-nameservers-only"* ]] && needs_only_arg=true
|
|
fi
|
|
|
|
if $needs_ns_arg; then
|
|
_kubectl patch deployment cert-manager \
|
|
--namespace "$ns" \
|
|
--type=json \
|
|
-p "[{\"op\":\"add\",\"path\":\"/spec/template/spec/containers/0/args/-\",\"value\":\"--dns01-recursive-nameservers=${ns_csv}\"}]" \
|
|
>/dev/null 2>&1 || true
|
|
patched=true
|
|
fi
|
|
|
|
if $needs_only_arg; then
|
|
_kubectl patch deployment cert-manager \
|
|
--namespace "$ns" \
|
|
--type=json \
|
|
-p '[{"op":"add","path":"/spec/template/spec/containers/0/args/-","value":"--dns01-recursive-nameservers-only"}]' \
|
|
>/dev/null 2>&1 || true
|
|
patched=true
|
|
fi
|
|
|
|
if $patched; then
|
|
echo " [patch_recursive_dns] args added to deployment"
|
|
else
|
|
echo " [patch_recursive_dns] args already present — no change"
|
|
fi
|
|
_kubectl rollout status deployment cert-manager -n "$ns" --timeout=120s
|
|
}
|
|
|
|
_method_wait-ready() {
|
|
local kind="${PLAN_PARAM_KIND:-deployment}"
|
|
local ns="${PLAN_PARAM_NAMESPACE:-cert-manager}"
|
|
local name="${PLAN_PARAM_NAME:-}"
|
|
local timeout="${PLAN_PARAM_TIMEOUT:-120s}"
|
|
[ -n "$name" ] || { echo "ERROR: PLAN_PARAM_NAME not set for wait-ready" >&2; exit 1; }
|
|
_kubectl wait --for=condition=Available \
|
|
"${kind}/${name}" \
|
|
--namespace "$ns" \
|
|
--timeout="$timeout"
|
|
}
|