talos-cluster/scripts/bootstrap-apps.sh

145 lines
4.7 KiB
Bash
Executable File

#!/usr/bin/env bash
set -Eeuo pipefail
source "$(dirname "${0}")/lib/common.sh"
export LOG_LEVEL="debug"
export ROOT_DIR="$(git rev-parse --show-toplevel)"
# Talos requires the nodes to be 'Ready=False' before applying resources
function wait_for_nodes() {
log debug "Waiting for nodes to be available"
# Skip waiting if all nodes are 'Ready=True'
if kubectl wait nodes --for=condition=Ready=True --all --timeout=10s &>/dev/null; then
log info "Nodes are available and ready, skipping wait for nodes"
return
fi
# Wait for all nodes to be 'Ready=False'
until kubectl wait nodes --for=condition=Ready=False --all --timeout=10s &>/dev/null; do
log info "Nodes are not available, waiting for nodes to be available. Retrying in 10 seconds..."
sleep 10
done
}
# Namespaces to be applied before the SOPS secrets are installed
function apply_namespaces() {
log debug "Applying namespaces"
local -r apps_dir="${ROOT_DIR}/kubernetes/apps"
if [[ ! -d "${apps_dir}" ]]; then
log error "Directory does not exist" "directory=${apps_dir}"
fi
for app in "${apps_dir}"/*/; do
namespace=$(basename "${app}")
# Check if the namespace resources are up-to-date
if kubectl get namespace "${namespace}" &>/dev/null; then
log info "Namespace resource is up-to-date" "resource=${namespace}"
continue
fi
# Apply the namespace resources
if kubectl create namespace "${namespace}" --dry-run=client --output=yaml \
| kubectl apply --server-side --filename - &>/dev/null;
then
log info "Namespace resource applied" "resource=${namespace}"
else
log error "Failed to apply namespace resource" "resource=${namespace}"
fi
done
}
# SOPS secrets to be applied before the helmfile charts are installed
function apply_sops_secrets() {
log debug "Applying secrets"
local -r secrets=(
"${ROOT_DIR}/bootstrap/github-deploy-key.sops.yaml"
"${ROOT_DIR}/bootstrap/sops-age.sops.yaml"
"${ROOT_DIR}/kubernetes/components/sops/cluster-secrets.sops.yaml"
)
for secret in "${secrets[@]}"; do
if [ ! -f "${secret}" ]; then
log warn "File does not exist" "file=${secret}"
continue
fi
# Check if the secret resources are up-to-date
if sops exec-file "${secret}" "kubectl --namespace flux-system diff --filename {}" &>/dev/null; then
log info "Secret resource is up-to-date" "resource=$(basename "${secret}" ".sops.yaml")"
continue
fi
# Apply secret resources
if sops exec-file "${secret}" "kubectl --namespace flux-system apply --server-side --filename {}" &>/dev/null; then
log info "Secret resource applied successfully" "resource=$(basename "${secret}" ".sops.yaml")"
else
log error "Failed to apply secret resource" "resource=$(basename "${secret}" ".sops.yaml")"
fi
done
}
# CRDs to be applied before the helmfile charts are installed
function apply_crds() {
log debug "Applying CRDs"
local -r helmfile_file="${ROOT_DIR}/bootstrap/helmfile.d/00-crds.yaml"
if [[ ! -f "${helmfile_file}" ]]; then
log fatal "File does not exist" "file" "${helmfile_file}"
fi
if ! crds=$(helmfile --file "${helmfile_file}" template --quiet | yq eval-all --exit-status 'select(.kind == "CustomResourceDefinition")') || [[ -z "${crds}" ]]; then
log fatal "Failed to render CRDs from Helmfile" "file" "${helmfile_file}"
fi
if echo "${crds}" | kubectl diff --filename - &>/dev/null; then
log info "CRDs are up-to-date"
return
fi
if ! echo "${crds}" | kubectl apply --server-side --filename - &>/dev/null; then
log fatal "Failed to apply crds from Helmfile" "file" "${helmfile_file}"
fi
log info "CRDs applied successfully"
}
# Sync Helm releases
function sync_helm_releases() {
log debug "Syncing Helm releases"
local -r helmfile_file="${ROOT_DIR}/bootstrap/helmfile.d/01-apps.yaml"
if [[ ! -f "${helmfile_file}" ]]; then
log error "File does not exist" "file=${helmfile_file}"
fi
if ! helmfile --file "${helmfile_file}" sync --hide-notes; then
log error "Failed to sync Helm releases"
fi
log info "Helm releases synced successfully"
}
function main() {
check_env KUBECONFIG TALOSCONFIG
check_cli helmfile kubectl kustomize sops talhelper yq
# Apply resources and Helm releases
wait_for_nodes
apply_namespaces
apply_sops_secrets
apply_crds
sync_helm_releases
log info "Congrats! The cluster is bootstrapped and Flux is syncing the Git repository"
}
main "$@"