prole/etc/init_argocd.sh

199 lines
6.9 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
# init_argocd.sh
# Deploy and manage ArgoCD as part of the common core stack.
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
# Shared option parsing for common core scripts
# shellcheck disable=SC1090
source "$SCRIPT_DIR/common_core_lib.sh"
common_core_preparse_config "$@"
# shellcheck disable=SC1090
source "$SCRIPT_DIR/knoe_cfg.sh"
set -- "${COMMON_CORE_ARGS[@]}"
common_core_parse_args "$@"
if [[ "${COMMON_CORE_HELP:-0}" == 1 ]]; then
common_core_usage "$0"
exit 0
fi
if [[ -n "${COMMON_CORE_PARSE_ERROR:-}" ]]; then
echo "ERROR: ${COMMON_CORE_PARSE_ERROR}" >&2
common_core_usage "$0"
exit 2
fi
ACTION="$COMMON_CORE_ACTION"
REPO_ROOT="${KNOE_HOME:-$(cd "$SCRIPT_DIR/.." && pwd)}"
GKE_MANIFEST_DIR="${GKE_MANIFEST_DIR:-$REPO_ROOT/deploy/gcp/gke}"
if [[ -d "$SCRIPT_DIR/../k8s/argocd" ]]; then
ARGOCD_MANIFEST_DIR="$SCRIPT_DIR/../k8s/argocd"
elif [[ -n "${KNOE_HOME:-}" && -d "$KNOE_HOME/k8s/argocd" ]]; then
ARGOCD_MANIFEST_DIR="$KNOE_HOME/k8s/argocd"
else
ARGOCD_MANIFEST_DIR="$SCRIPT_DIR/../k8s/argocd"
fi
ARGOCD_MANIFEST_FILE=${ARGOCD_MANIFEST_FILE:-"$ARGOCD_MANIFEST_DIR/install.yaml"}
ARGOCD_NAMESPACE_DEFAULT="${ARGOCD_NAMESPACE:-argocd}"
ARGOCD_NAMESPACE="$(common_core_resolve_namespace "$ARGOCD_NAMESPACE_DEFAULT")"
common_core_apply_namespace "$ARGOCD_NAMESPACE"
export ARGOCD_NAMESPACE
ARGOCD_LABEL_SELECTOR=${ARGOCD_LABEL_SELECTOR:-"app.kubernetes.io/part-of=argocd"}
ARGOCD_SERVER_SERVICE=${ARGOCD_SERVER_SERVICE:-argocd-server}
ARGOCD_PORT_FORWARD_LOCAL=${ARGOCD_PORT_FORWARD_LOCAL:-8081}
ARGOCD_PORT_FORWARD_REMOTE=${ARGOCD_PORT_FORWARD_REMOTE:-80}
ARGOCD_NODE_SELECTOR=${ARGOCD_NODE_SELECTOR:-}
# ── Google Workspace OIDC (applied when all three vars are set) ───────────────
PLATFORM_DOMAIN="${PLATFORM_DOMAIN:-}"
FRONTDOOR_HOST="${FRONTDOOR_HOST:-}"
BOOTSTRAP_ADMIN_EMAIL="${BOOTSTRAP_ADMIN_EMAIL:-}"
ensure_tools() {
command -v kubectl >/dev/null || { echo "Missing required tool: kubectl" >&2; exit 1; }
}
ensure_namespace() {
if ! kubectl get namespace "$ARGOCD_NAMESPACE" >/dev/null 2>&1; then
echo "Creating namespace '$ARGOCD_NAMESPACE' ..."
kubectl create namespace "$ARGOCD_NAMESPACE" >/dev/null 2>&1 || true
fi
}
render_manifest() {
if [[ ! -f "$ARGOCD_MANIFEST_FILE" ]]; then
echo "ERROR: ArgoCD manifest not found: $ARGOCD_MANIFEST_FILE" >&2
exit 1
fi
knoe_render_manifest "$ARGOCD_MANIFEST_FILE" | sed "s|\\${ARGOCD_NAMESPACE}|$ARGOCD_NAMESPACE|g"
}
resolve_argocd_node_selector() {
if [[ -n "$ARGOCD_NODE_SELECTOR" ]]; then
printf '%s' "$ARGOCD_NODE_SELECTOR"
return 0
fi
local node=""
node=$(kubectl get nodes -l 'node-role.kubernetes.io/control-plane' -o jsonpath='{.items[0].metadata.name}' 2>/dev/null || true)
if [[ -n "$node" ]]; then
printf 'kubernetes.io/hostname=%s' "$node"
fi
}
apply_argocd_node_selector() {
local selector
selector="$(resolve_argocd_node_selector)"
if [[ -z "$selector" ]]; then
return 0
fi
local key="${selector%%=*}"
local val="${selector#*=}"
if [[ -z "$key" || -z "$val" ]]; then
echo "WARN: invalid ARGOCD_NODE_SELECTOR '$selector' (expected key=value); skipping." >&2
return 0
fi
for target in \
deployment/argocd-applicationset-controller \
deployment/argocd-dex-server \
deployment/argocd-notifications-controller \
deployment/argocd-repo-server \
deployment/argocd-server \
deployment/argocd-redis \
statefulset/argocd-application-controller; do
kubectl -n "$ARGOCD_NAMESPACE" patch "$target" \
--type merge \
-p "{\"spec\":{\"template\":{\"spec\":{\"nodeSelector\":{\"$key\":\"$val\"}}}}}" >/dev/null 2>&1 || true
done
}
apply_argocd() {
echo "Applying ArgoCD manifest to namespace '$ARGOCD_NAMESPACE' ..."
render_manifest | kubectl apply --server-side --force-conflicts --field-manager=knoe-installer --validate=false -n "$ARGOCD_NAMESPACE" -f -
apply_argocd_node_selector
kubectl rollout status deploy/argocd-server -n "$ARGOCD_NAMESPACE" --timeout=${ROLLOUT_TIMEOUT:-300s} || true
kubectl rollout status deploy/argocd-repo-server -n "$ARGOCD_NAMESPACE" --timeout=${ROLLOUT_TIMEOUT:-300s} || true
kubectl rollout status deploy/argocd-dex-server -n "$ARGOCD_NAMESPACE" --timeout=${ROLLOUT_TIMEOUT:-300s} || true
kubectl rollout status deploy/argocd-applicationset-controller -n "$ARGOCD_NAMESPACE" --timeout=${ROLLOUT_TIMEOUT:-300s} || true
kubectl rollout status deploy/argocd-notifications-controller -n "$ARGOCD_NAMESPACE" --timeout=${ROLLOUT_TIMEOUT:-300s} || true
kubectl rollout status deploy/argocd-redis -n "$ARGOCD_NAMESPACE" --timeout=${ROLLOUT_TIMEOUT:-300s} || true
kubectl rollout status statefulset/argocd-application-controller -n "$ARGOCD_NAMESPACE" --timeout=${ROLLOUT_TIMEOUT:-300s} || true
}
apply_argocd_oidc_config() {
local cm_file="$GKE_MANIFEST_DIR/argocd-oidc-cm.yaml"
if [[ -z "$PLATFORM_DOMAIN" || -z "$FRONTDOOR_HOST" || -z "$BOOTSTRAP_ADMIN_EMAIL" ]]; then
return 0
fi
if [[ ! -f "$cm_file" ]]; then
echo "WARN: ArgoCD OIDC config not found at $cm_file; skipping OIDC patch." >&2
return 0
fi
echo "Applying ArgoCD OIDC config (issuer=https://${FRONTDOOR_HOST}/auth) ..."
PLATFORM_DOMAIN="$PLATFORM_DOMAIN" \
FRONTDOOR_HOST="$FRONTDOOR_HOST" \
BOOTSTRAP_ADMIN_EMAIL="$BOOTSTRAP_ADMIN_EMAIL" \
envsubst < "$cm_file" \
| kubectl apply --server-side --force-conflicts \
--field-manager=knoe-installer -f -
}
rollout_restart_argocd() {
kubectl -n "$ARGOCD_NAMESPACE" rollout restart deploy/argocd-server deploy/argocd-repo-server \
deploy/argocd-dex-server deploy/argocd-applicationset-controller deploy/argocd-notifications-controller \
deploy/argocd-redis >/dev/null 2>&1 || true
kubectl -n "$ARGOCD_NAMESPACE" rollout restart statefulset/argocd-application-controller >/dev/null 2>&1 || true
}
delete_argocd() {
echo "Removing ArgoCD resources from namespace '$ARGOCD_NAMESPACE' ..."
render_manifest | kubectl delete -n "$ARGOCD_NAMESPACE" -f - --ignore-not-found
}
status_argocd() {
kubectl -n "$ARGOCD_NAMESPACE" get deploy,statefulset,svc -l "$ARGOCD_LABEL_SELECTOR" 2>/dev/null || true
kubectl -n "$ARGOCD_NAMESPACE" get pods -l "$ARGOCD_LABEL_SELECTOR" 2>/dev/null || true
}
case "$ACTION" in
start|initialize|update|reload)
ensure_tools
ensure_namespace
apply_argocd
apply_argocd_oidc_config
knoe_register_port_forward "argocd" "$ARGOCD_NAMESPACE" "svc/${ARGOCD_SERVER_SERVICE}" \
"$ARGOCD_PORT_FORWARD_LOCAL" "$ARGOCD_PORT_FORWARD_REMOTE" "0.0.0.0" "TCP" "ArgoCD"
;;
restart)
ensure_tools
ensure_namespace
apply_argocd
rollout_restart_argocd
apply_argocd_oidc_config
knoe_register_port_forward "argocd" "$ARGOCD_NAMESPACE" "svc/${ARGOCD_SERVER_SERVICE}" \
"$ARGOCD_PORT_FORWARD_LOCAL" "$ARGOCD_PORT_FORWARD_REMOTE" "0.0.0.0" "TCP" "ArgoCD"
;;
stop)
ensure_tools
delete_argocd
;;
status)
ensure_tools
status_argocd
;;
*)
common_core_usage "$0"
exit 1
;;
esac