218 lines
6.7 KiB
Bash
218 lines
6.7 KiB
Bash
|
|
#!/usr/bin/env bash
|
||
|
|
set -euo pipefail
|
||
|
|
|
||
|
|
# Kubernetes workspace bootstrap script
|
||
|
|
#
|
||
|
|
# What this script handles:
|
||
|
|
# 1) kubectl context setup
|
||
|
|
# 2) k9s local config setup
|
||
|
|
# 3) Flux bootstrap to a Git repository
|
||
|
|
#
|
||
|
|
# Environment variables:
|
||
|
|
# - ENV_FILE: Optional env file path to load before execution (default: .env)
|
||
|
|
# - KUBECONFIG_SOURCE: Optional path to a kubeconfig file to copy to ~/.kube/config
|
||
|
|
# - KUBE_CONTEXT: Optional kube context name to switch to
|
||
|
|
# - APPLY_K9S_CONFIG: true|false (default: true)
|
||
|
|
# - FORCE_K9S_CONFIG: true|false (default: false)
|
||
|
|
# - FLUX_BOOTSTRAP: true|false (default: true)
|
||
|
|
# - FLUX_PROVIDER: gitea|forgejo|github|gitlab (default: gitea)
|
||
|
|
# - FLUX_GIT_URL: Git URL for flux bootstrap git (required for gitea/forgejo)
|
||
|
|
# - FLUX_GIT_BRANCH: Git branch for Flux manifests (default: main)
|
||
|
|
# - FLUX_GIT_PATH: Repository path for Flux manifests (default: clusters/<current-context>)
|
||
|
|
# - FLUX_NAMESPACE: Flux namespace (default: flux-system)
|
||
|
|
# - FLUX_GIT_PRIVATE_KEY_FILE: SSH private key for bootstrap auth (default: ~/.ssh/id_ed25519)
|
||
|
|
# - FLUX_INSECURE_HOSTKEYS: true|false (default: false)
|
||
|
|
# - FLUX_GITHUB_OWNER / FLUX_GITHUB_REPO: required for github provider
|
||
|
|
# - FLUX_GITLAB_OWNER / FLUX_GITLAB_REPO: required for gitlab provider
|
||
|
|
# - FLUX_GITLAB_HOSTNAME: optional gitlab hostname (default: gitlab.com)
|
||
|
|
|
||
|
|
require_cmd() {
|
||
|
|
local cmd="$1"
|
||
|
|
if ! command -v "$cmd" >/dev/null 2>&1; then
|
||
|
|
echo "Required command not found: $cmd"
|
||
|
|
echo "Install dependencies first (kubectl, k9s, flux, git)."
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
}
|
||
|
|
|
||
|
|
append_once() {
|
||
|
|
local file="$1"
|
||
|
|
local marker="$2"
|
||
|
|
local payload="$3"
|
||
|
|
|
||
|
|
touch "$file"
|
||
|
|
if ! grep -q "$marker" "$file"; then
|
||
|
|
printf "\n%s\n" "$payload" >> "$file"
|
||
|
|
fi
|
||
|
|
}
|
||
|
|
|
||
|
|
load_env_file() {
|
||
|
|
local env_file="$1"
|
||
|
|
if [ -f "$env_file" ]; then
|
||
|
|
echo "Loading environment from: $env_file"
|
||
|
|
set -a
|
||
|
|
# shellcheck disable=SC1090
|
||
|
|
. "$env_file"
|
||
|
|
set +a
|
||
|
|
fi
|
||
|
|
}
|
||
|
|
|
||
|
|
echo "Starting Kubernetes workspace bootstrap..."
|
||
|
|
|
||
|
|
load_env_file "${ENV_FILE:-.env}"
|
||
|
|
|
||
|
|
require_cmd kubectl
|
||
|
|
require_cmd k9s
|
||
|
|
require_cmd flux
|
||
|
|
require_cmd git
|
||
|
|
|
||
|
|
mkdir -p "$HOME/.kube"
|
||
|
|
if [ -n "${KUBECONFIG_SOURCE:-}" ]; then
|
||
|
|
if [ ! -f "$KUBECONFIG_SOURCE" ]; then
|
||
|
|
echo "KUBECONFIG_SOURCE does not exist: $KUBECONFIG_SOURCE"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo "Copying kubeconfig from KUBECONFIG_SOURCE to ~/.kube/config"
|
||
|
|
install -m 600 "$KUBECONFIG_SOURCE" "$HOME/.kube/config"
|
||
|
|
fi
|
||
|
|
|
||
|
|
if [ ! -f "$HOME/.kube/config" ]; then
|
||
|
|
echo "No kubeconfig found at ~/.kube/config"
|
||
|
|
echo "Provide KUBECONFIG_SOURCE or create ~/.kube/config before running this script."
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
if [ -n "${KUBE_CONTEXT:-}" ]; then
|
||
|
|
echo "Switching kubectl context to: $KUBE_CONTEXT"
|
||
|
|
kubectl config use-context "$KUBE_CONTEXT"
|
||
|
|
fi
|
||
|
|
|
||
|
|
CURRENT_CONTEXT="$(kubectl config current-context 2>/dev/null || true)"
|
||
|
|
if [ -z "$CURRENT_CONTEXT" ]; then
|
||
|
|
echo "Unable to determine current kubectl context."
|
||
|
|
echo "Set KUBE_CONTEXT to a valid context and try again."
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo "Current kubectl context: $CURRENT_CONTEXT"
|
||
|
|
if ! kubectl cluster-info >/dev/null 2>&1; then
|
||
|
|
echo "kubectl cannot reach the cluster for context: $CURRENT_CONTEXT"
|
||
|
|
echo "Validate credentials/network and rerun."
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
if [ "${APPLY_K9S_CONFIG:-true}" = "true" ]; then
|
||
|
|
mkdir -p "$HOME/.config/k9s"
|
||
|
|
|
||
|
|
if [ ! -f "$HOME/.config/k9s/config.yaml" ] || [ "${FORCE_K9S_CONFIG:-false}" = "true" ]; then
|
||
|
|
echo "Writing k9s config to ~/.config/k9s/config.yaml"
|
||
|
|
cat > "$HOME/.config/k9s/config.yaml" <<EOF
|
||
|
|
k9s:
|
||
|
|
refreshRate: 2
|
||
|
|
maxConnRetry: 5
|
||
|
|
readOnly: false
|
||
|
|
noIcons: false
|
||
|
|
logger:
|
||
|
|
tail: 200
|
||
|
|
buffer: 5000
|
||
|
|
sinceSeconds: -1
|
||
|
|
currentContext: ${CURRENT_CONTEXT}
|
||
|
|
EOF
|
||
|
|
else
|
||
|
|
echo "k9s config already exists; keeping existing file."
|
||
|
|
fi
|
||
|
|
fi
|
||
|
|
|
||
|
|
append_once "$HOME/.bashrc" 'alias k9sctx=' "# Kubernetes workspace helpers\nalias k9sctx='kubectl config current-context'\nalias k9sn='k9s -n kube-system'"
|
||
|
|
|
||
|
|
if [ "${FLUX_BOOTSTRAP:-true}" = "true" ]; then
|
||
|
|
FLUX_PROVIDER="${FLUX_PROVIDER:-gitea}"
|
||
|
|
FLUX_GIT_BRANCH="${FLUX_GIT_BRANCH:-main}"
|
||
|
|
FLUX_NAMESPACE="${FLUX_NAMESPACE:-flux-system}"
|
||
|
|
FLUX_GIT_PATH="${FLUX_GIT_PATH:-clusters/${CURRENT_CONTEXT}}"
|
||
|
|
|
||
|
|
echo "Running flux preflight checks..."
|
||
|
|
flux check --pre
|
||
|
|
|
||
|
|
case "${FLUX_PROVIDER}" in
|
||
|
|
gitea|forgejo)
|
||
|
|
if [ -z "${FLUX_GIT_URL:-}" ]; then
|
||
|
|
echo "FLUX_GIT_URL is required for provider=${FLUX_PROVIDER}"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
FLUX_GIT_PRIVATE_KEY_FILE="${FLUX_GIT_PRIVATE_KEY_FILE:-$HOME/.ssh/id_ed25519}"
|
||
|
|
if [ ! -f "$FLUX_GIT_PRIVATE_KEY_FILE" ]; then
|
||
|
|
echo "Flux private key file not found: $FLUX_GIT_PRIVATE_KEY_FILE"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo "Bootstrapping Flux (${FLUX_PROVIDER}) to ${FLUX_GIT_URL} (branch=${FLUX_GIT_BRANCH}, path=${FLUX_GIT_PATH})"
|
||
|
|
flux_cmd=(
|
||
|
|
flux bootstrap git
|
||
|
|
--url="$FLUX_GIT_URL"
|
||
|
|
--branch="$FLUX_GIT_BRANCH"
|
||
|
|
--path="$FLUX_GIT_PATH"
|
||
|
|
--namespace="$FLUX_NAMESPACE"
|
||
|
|
--private-key-file="$FLUX_GIT_PRIVATE_KEY_FILE"
|
||
|
|
)
|
||
|
|
|
||
|
|
if [ "${FLUX_INSECURE_HOSTKEYS:-false}" = "true" ]; then
|
||
|
|
flux_cmd+=(--insecure-hostkey)
|
||
|
|
fi
|
||
|
|
|
||
|
|
"${flux_cmd[@]}"
|
||
|
|
;;
|
||
|
|
github)
|
||
|
|
if [ -z "${FLUX_GITHUB_OWNER:-}" ] || [ -z "${FLUX_GITHUB_REPO:-}" ]; then
|
||
|
|
echo "FLUX_GITHUB_OWNER and FLUX_GITHUB_REPO are required for provider=github"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
if [ -z "${GITHUB_TOKEN:-}" ]; then
|
||
|
|
echo "GITHUB_TOKEN must be set in environment for provider=github"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo "Bootstrapping Flux (github) to ${FLUX_GITHUB_OWNER}/${FLUX_GITHUB_REPO}"
|
||
|
|
flux bootstrap github \
|
||
|
|
--owner="$FLUX_GITHUB_OWNER" \
|
||
|
|
--repository="$FLUX_GITHUB_REPO" \
|
||
|
|
--branch="$FLUX_GIT_BRANCH" \
|
||
|
|
--path="$FLUX_GIT_PATH" \
|
||
|
|
--personal \
|
||
|
|
--namespace="$FLUX_NAMESPACE"
|
||
|
|
;;
|
||
|
|
gitlab)
|
||
|
|
if [ -z "${FLUX_GITLAB_OWNER:-}" ] || [ -z "${FLUX_GITLAB_REPO:-}" ]; then
|
||
|
|
echo "FLUX_GITLAB_OWNER and FLUX_GITLAB_REPO are required for provider=gitlab"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
if [ -z "${GITLAB_TOKEN:-}" ]; then
|
||
|
|
echo "GITLAB_TOKEN must be set in environment for provider=gitlab"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
FLUX_GITLAB_HOSTNAME="${FLUX_GITLAB_HOSTNAME:-gitlab.com}"
|
||
|
|
echo "Bootstrapping Flux (gitlab) to ${FLUX_GITLAB_OWNER}/${FLUX_GITLAB_REPO} on ${FLUX_GITLAB_HOSTNAME}"
|
||
|
|
flux bootstrap gitlab \
|
||
|
|
--hostname="$FLUX_GITLAB_HOSTNAME" \
|
||
|
|
--owner="$FLUX_GITLAB_OWNER" \
|
||
|
|
--repository="$FLUX_GITLAB_REPO" \
|
||
|
|
--branch="$FLUX_GIT_BRANCH" \
|
||
|
|
--path="$FLUX_GIT_PATH" \
|
||
|
|
--namespace="$FLUX_NAMESPACE"
|
||
|
|
;;
|
||
|
|
*)
|
||
|
|
echo "Unsupported FLUX_PROVIDER: ${FLUX_PROVIDER}"
|
||
|
|
echo "Supported values: gitea, forgejo, github, gitlab"
|
||
|
|
exit 1
|
||
|
|
;;
|
||
|
|
esac
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo "Kubernetes workspace setup complete."
|
||
|
|
echo "Open a new shell or run: source ~/.bashrc"
|