Files
home-cluster/configure
T
Adam Petrovic 8c30a120da fix setup_prometheus_endpoints in configure (#790)
The kubeControllerManager endpoints were being cleared on each iteration of the loop over control nodes leading to only the last control node being added. Instead the array has been cleared outside of the loop.
2023-06-15 06:58:18 -04:00

546 lines
23 KiB
Bash
Executable File

#!/usr/bin/env bash
set -o errexit
set -o pipefail
# shellcheck disable=SC2155
export PROJECT_DIR=$(git rev-parse --show-toplevel)
# shellcheck disable=SC2155
export SOPS_AGE_KEY_FILE=~/.config/sops/age/keys.txt
# shellcheck disable=SC1091
source "${PROJECT_DIR}/.config.env"
show_help() {
cat << EOF
Usage: $(basename "$0") <options>
-h, --help Display help
--verify Verify .config.env settings
EOF
}
main() {
local verify=
parse_command_line "$@"
if [[ "${verify}" == 1 ]]; then
verify_start
verify_binaries
verify_master_count
verify_ansible_hosts
verify_metallb
verify_kubevip
verify_cluster_service_cidrs
verify_addressing
verify_age
verify_git_repository
verify_cloudflare
verify_success
else
# generate sops configuration file
envsubst < "${PROJECT_DIR}/tmpl/.sops.yaml" \
> "${PROJECT_DIR}/.sops.yaml"
# generate cluster settings
envsubst < "${PROJECT_DIR}/tmpl/kubernetes/flux/cluster-settings.yaml" \
> "${PROJECT_DIR}/kubernetes/flux/vars/cluster-settings.yaml"
envsubst < "${PROJECT_DIR}/tmpl/kubernetes/flux/cluster.yaml" \
> "${PROJECT_DIR}/kubernetes/flux/config/cluster.yaml"
# generate secrets
envsubst < "${PROJECT_DIR}/tmpl/kubernetes/cluster-secrets.sops.yaml" \
> "${PROJECT_DIR}/kubernetes/flux/vars/cluster-secrets.sops.yaml"
sops --encrypt --in-place "${PROJECT_DIR}/kubernetes/flux/vars/cluster-secrets.sops.yaml"
envsubst < "${PROJECT_DIR}/tmpl/kubernetes/cert-manager-secret.sops.yaml" \
> "${PROJECT_DIR}/kubernetes/apps/cert-manager/cert-manager/issuers/secret.sops.yaml"
sops --encrypt --in-place "${PROJECT_DIR}/kubernetes/apps/cert-manager/cert-manager/issuers/secret.sops.yaml"
envsubst < "${PROJECT_DIR}/tmpl/kubernetes/cloudflared-secret.sops.yaml" \
> "${PROJECT_DIR}/kubernetes/apps/networking/cloudflared/app/secret.sops.yaml"
sops --encrypt --in-place "${PROJECT_DIR}/kubernetes/apps/networking/cloudflared/app/secret.sops.yaml"
envsubst < "${PROJECT_DIR}/tmpl/kubernetes/external-dns-secret.sops.yaml" \
> "${PROJECT_DIR}/kubernetes/apps/networking/external-dns/app/secret.sops.yaml"
sops --encrypt --in-place "${PROJECT_DIR}/kubernetes/apps/networking/external-dns/app/secret.sops.yaml"
# generate ansible settings
envsubst < "${PROJECT_DIR}/tmpl/ansible/supplemental.yml" \
> "${PROJECT_DIR}/ansible/inventory/group_vars/kubernetes/supplemental.yml"
# generate ansible hosts file and secrets
generate_ansible_hosts
generate_ansible_host_secrets
setup_github_webhook
setup_weave_gitops
setup_grafana_admin
setup_prometheus_endpoints
success
fi
}
parse_command_line() {
while :; do
case "${1:-}" in
-h|--help)
show_help
exit
;;
--verify)
verify=1
;;
*)
break
;;
esac
shift
done
if [[ -z "$verify" ]]; then
verify=0
fi
}
_has_binary() {
command -v "${1}" >/dev/null 2>&1 || {
_log "ERROR(${FUNCNAME[0]})" "${1} is not installed or not found in \$PATH"
exit 1
}
_log "INFO(${FUNCNAME[0]})" "Found CLI tool ${1} and it is in \$PATH"
}
_has_optional_envar() {
local option="${1}"
# shellcheck disable=SC2015
[[ "${!option}" == "" ]] && {
_log "WARN" "Unset optional variable ${option}"
} || {
_log "INFO(${FUNCNAME[0]})" "Found variable '${option}' with value '${!option}'"
}
}
_has_envar() {
local option="${1}"
local secret="${2:-false}"
local value=
# shellcheck disable=SC2015
if [[ "${!option}" == "" ]]; then
_log "ERROR(${FUNCNAME[0]})" "Unset variable ${option}"
exit 1
fi
value="${!option}"
if [[ $secret == "true" ]]; then
value="***"
fi
_log "INFO(${FUNCNAME[0]})" "Found variable '${option}' with value '${value}'"
}
_has_valid_ip() {
local ip="${1}"
local variable_name="${2}"
if ! ipcalc "${ip}" | awk 'BEGIN{FS=":"; is_invalid=0} /^INVALID/ {is_invalid=1; print $1} END{exit is_invalid}' >/dev/null 2>&1; then
_log "INFO(${FUNCNAME[0]})" "Variable '${variable_name}' has an invalid IP address '${ip}'"
exit 1
else
_log "INFO(${FUNCNAME[0]})" "Variable '${variable_name}' has a valid IP address '${ip}'"
fi
}
verify_addressing() {
local found_kube_vip="false"
local found_k8s_gateway="false"
local found_ingress="false"
# Verify the metallb min and metallb ceiling are in the same network
metallb_subnet_min=$(echo "${BOOTSTRAP_METALLB_LB_RANGE}" | cut -d- -f1 | cut -d. -f1,2,3)
metallb_subnet_ceil=$(echo "${BOOTSTRAP_METALLB_LB_RANGE}" | cut -d- -f2 | cut -d. -f1,2,3)
if [[ "${metallb_subnet_min}" != "${metallb_subnet_ceil}" ]]; then
_log "ERROR(${FUNCNAME[0]})" "The provided MetalLB IP range '${BOOTSTRAP_METALLB_LB_RANGE}' is not in the same subnet"
exit 1
fi
# Verify the node IP addresses are on the same network as the metallb range
for var in "${!BOOTSTRAP_ANSIBLE_HOST_ADDR_@}"; do
node_subnet=$(echo "${!var}" | cut -d. -f1,2,3)
if [[ "${node_subnet}" != "${metallb_subnet_min}" ]]; then
_log "ERROR(${FUNCNAME[0]})" "The subnet for node '${!var}' is not in the same subnet as the provided metallb range '${BOOTSTRAP_METALLB_LB_RANGE}'"
exit 1
fi
done
# Verify the kube-vip IP is in the same network as the metallb range
kubevip_subnet=$(echo "${BOOTSTRAP_KUBE_VIP_ADDR}" | cut -d. -f1,2,3)
if [[ "${kubevip_subnet}" != "${metallb_subnet_min}" ]]; then
_log "ERROR(${FUNCNAME[0]})" "The subnet for kupe-vip '${BOOTSTRAP_KUBE_VIP_ADDR}' is not the same subnet as the provided metallb range '${BOOTSTRAP_METALLB_LB_RANGE}'"
exit 1
fi
# Depending on the IP address, verify if it should be in the metallb range or not
metallb_octet_min=$(echo "${BOOTSTRAP_METALLB_LB_RANGE}" | cut -d- -f1 | cut -d. -f4)
metallb_octet_ceil=$(echo "${BOOTSTRAP_METALLB_LB_RANGE}" | cut -d- -f2 | cut -d. -f4)
for (( octet=metallb_octet_min; octet<=metallb_octet_ceil; octet++ )); do
addr="${metallb_subnet_min}.${octet}"
if [[ "${addr}" == "${BOOTSTRAP_KUBE_VIP_ADDR}" ]]; then
found_kube_vip="true"
fi
if [[ "${addr}" == "${BOOTSTRAP_METALLB_K8S_GATEWAY_ADDR}" ]]; then
found_k8s_gateway="true"
fi
if [[ "${addr}" == "${BOOTSTRAP_METALLB_INGRESS_ADDR}" ]]; then
found_ingress="true"
fi
for var in "${!BOOTSTRAP_ANSIBLE_HOST_ADDR_@}"; do
if [[ "${!var}" == "${addr}" ]]; then
_log "ERROR(${FUNCNAME[0]})" "The IP for node '${!var}' should NOT be in the provided metallb range '${BOOTSTRAP_METALLB_LB_RANGE}'"
exit 1
fi
done
done
if [[ "${found_kube_vip}" == "true" ]]; then
_log "ERROR(${FUNCNAME[0]})" "The IP for kube-vip '${BOOTSTRAP_KUBE_VIP_ADDR}' should NOT be in the provided metallb range '${BOOTSTRAP_METALLB_LB_RANGE}'"
exit 1
fi
if [[ "${found_k8s_gateway}" == "false" ]]; then
_log "ERROR(${FUNCNAME[0]})" "The IP for k8s_gateway '${BOOTSTRAP_METALLB_K8S_GATEWAY_ADDR}' should be in the provided metallb range '${BOOTSTRAP_METALLB_LB_RANGE}'"
exit 1
fi
if [[ "${found_ingress}" == "false" ]]; then
_log "ERROR(${FUNCNAME[0]})" "The IP for ingress '${BOOTSTRAP_METALLB_INGRESS_ADDR}' should be in the provided metallb range '${BOOTSTRAP_METALLB_LB_RANGE}'"
exit 1
fi
}
verify_age() {
_has_envar "BOOTSTRAP_AGE_PUBLIC_KEY"
_has_envar "SOPS_AGE_KEY_FILE"
if [[ ! "$BOOTSTRAP_AGE_PUBLIC_KEY" =~ ^age.* ]]; then
_log "ERROR(${FUNCNAME[0]})" "BOOTSTRAP_AGE_PUBLIC_KEY does not start with age"
exit 1
else
_log "INFO(${FUNCNAME[0]})" "Age public key is in the correct format"
fi
if [[ ! -f ~/.config/sops/age/keys.txt ]]; then
_log "ERROR(${FUNCNAME[0]})" "Unable to find Age file keys.txt in ~/.config/sops/age"
exit 1
else
_log "INFO(${FUNCNAME[0]})" "Found Age public key '${BOOTSTRAP_AGE_PUBLIC_KEY}'"
fi
}
verify_binaries() {
_has_binary "age"
_has_binary "ansible"
_has_binary "envsubst"
_has_binary "flux"
_has_binary "git"
_has_binary "gitops"
_has_binary "ipcalc"
_has_binary "jq"
_has_binary "pip3"
_has_binary "sops"
_has_binary "ssh"
_has_binary "task"
_has_binary "yq"
if ! [[ "$(sops --version)" =~ 3\.[0-9]+\.[0-9]+ ]]; then
_log "ERROR(${FUNCNAME[0]})" "Incompatible sops version, make sure you are using the latest release of github.com/mozilla/sops"
exit 1
fi
if ! [[ "$(yq --version)" =~ 4\.[0-9]+\.[0-9]+ ]]; then
_log "ERROR(${FUNCNAME[0]})" "Incompatible yq version, make sure you are using the latest release of github.com/mikefarah/yq"
exit 1
fi
}
verify_kubevip() {
_has_envar "BOOTSTRAP_KUBE_VIP_ADDR"
_has_valid_ip "${BOOTSTRAP_KUBE_VIP_ADDR}" "BOOTSTRAP_KUBE_VIP_ADDR"
}
verify_metallb() {
_has_envar "BOOTSTRAP_METALLB_LB_RANGE"
_has_envar "BOOTSTRAP_METALLB_K8S_GATEWAY_ADDR"
_has_envar "BOOTSTRAP_METALLB_INGRESS_ADDR"
_has_valid_ip "$(echo "${BOOTSTRAP_METALLB_LB_RANGE}" | cut -d- -f1)" "BOOTSTRAP_METALLB_LB_RANGE"
_has_valid_ip "$(echo "${BOOTSTRAP_METALLB_LB_RANGE}" | cut -d- -f2)" "BOOTSTRAP_METALLB_LB_RANGE"
_has_valid_ip "${BOOTSTRAP_METALLB_K8S_GATEWAY_ADDR}" "BOOTSTRAP_METALLB_K8S_GATEWAY_ADDR"
_has_valid_ip "${BOOTSTRAP_METALLB_INGRESS_ADDR}" "BOOTSTRAP_METALLB_INGRESS_ADDR"
}
verify_cluster_service_cidrs() {
#TODO: Validate input is a CIDR range
_has_envar "BOOTSTRAP_CLUSTER_CIDR"
_has_envar "BOOTSTRAP_SERVICE_CIDR"
}
verify_git_repository() {
_has_envar "BOOTSTRAP_GIT_REPOSITORY"
export GIT_TERMINAL_PROMPT=0
pushd "$(mktemp -d)" >/dev/null 2>&1
[ "$(git ls-remote "${BOOTSTRAP_GIT_REPOSITORY}" 2> /dev/null)" ] || {
_log "ERROR(${FUNCNAME[0]})" "Unable to find the remote Git repository '${BOOTSTRAP_GIT_REPOSITORY}'"
exit 1
}
popd >/dev/null 2>&1
export GIT_TERMINAL_PROMPT=1
}
verify_master_count() {
local master_node_count=
master_node_count=0
for var in "${!BOOTSTRAP_ANSIBLE_HOST_ADDR_@}"; do
node_id=$(echo "${var}" | awk -F"_" '{print $5}')
node_control="BOOTSTRAP_ANSIBLE_CONTROL_NODE_${node_id}"
if [[ "${!node_control}" == "true" ]]; then
master_node_count=$((master_node_count+1))
fi
done
# Check for existance of master nodes and that their count is not an even number
if [[ ${master_node_count} -eq 0 || $((master_node_count%2)) -eq 0 ]]; then
_log "ERROR(${FUNCNAME[0]})" "You must have 1, 3 or an odd number of master nodes >=3 inorder for etcd to have quorum"
exit 1
fi
_log "INFO(${FUNCNAME[0]})" "Verified control plane node count"
}
verify_cloudflare() {
local errors=
local account_zone=
_has_envar "BOOTSTRAP_CLOUDFLARE_APITOKEN" "true"
_has_envar "BOOTSTRAP_CLOUDFLARE_DOMAIN" "true"
_has_envar "BOOTSTRAP_ACME_EMAIL" "true"
# Try to retrieve zone information from Cloudflare's API
account_zone=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=${BOOTSTRAP_CLOUDFLARE_DOMAIN}&status=active" \
-H "Authorization: Bearer ${BOOTSTRAP_CLOUDFLARE_APITOKEN}" \
-H "Content-Type: application/json"
)
if [[ "$(echo "${account_zone}" | jq ".success")" == "true" ]]; then
_log "INFO(${FUNCNAME[0]})" "Verified Cloudflare Account and Zone information"
else
errors=$(echo "${account_zone}" | jq -c ".errors")
_log "ERROR(${FUNCNAME[0]})" "Unable to get Cloudflare Account and Zone information ${errors}"
exit 1
fi
local cloudflare_tunnel=
_has_envar "BOOTSTRAP_CLOUDFLARE_ACCOUNT_TAG" "true"
_has_envar "BOOTSTRAP_CLOUDFLARE_TUNNEL_SECRET" "true"
_has_envar "BOOTSTRAP_CLOUDFLARE_TUNNEL_ID" "true"
# Try to retrieve the Cloudflare Tunnel information from Cloudflare's API
cloudflare_tunnel=$(curl -s -X GET "https://api.cloudflare.com/client/v4/accounts/${BOOTSTRAP_CLOUDFLARE_ACCOUNT_TAG}/cfd_tunnel/${BOOTSTRAP_CLOUDFLARE_TUNNEL_ID}" \
-H "Authorization: Bearer ${BOOTSTRAP_CLOUDFLARE_APITOKEN}" \
-H "Content-Type: application/json"
)
if [[ "$(echo "${cloudflare_tunnel}" | jq ".success")" == "true" ]]; then
_log "INFO(${FUNCNAME[0]})" "Verified Cloudflare Tunnel information"
else
errors=$(echo "${cloudflare_tunnel}" | jq -c ".errors")
_log "ERROR(${FUNCNAME[0]})" "Unable to get Cloudflare Tunnel information ${errors}"
exit 1
fi
}
verify_ansible_hosts() {
local node_id=
local node_addr=
local node_username=
local node_password=
local node_control=
local node_hostname=
local default_control_node_prefix=
local default_worker_node_prefix=
default_control_node_prefix="BOOTSTRAP_ANSIBLE_DEFAULT_CONTROL_NODE_HOSTNAME_PREFIX"
default_worker_node_prefix="BOOTSTRAP_ANSIBLE_DEFAULT_NODE_HOSTNAME_PREFIX"
_has_optional_envar "${default_control_node_prefix}"
_has_optional_envar "${default_worker_node_prefix}"
for var in "${!BOOTSTRAP_ANSIBLE_HOST_ADDR_@}"; do
node_id=$(echo "${var}" | awk -F"_" '{print $5}')
node_addr="BOOTSTRAP_ANSIBLE_HOST_ADDR_${node_id}"
node_username="BOOTSTRAP_ANSIBLE_SSH_USERNAME_${node_id}"
node_password="BOOTSTRAP_ANSIBLE_SUDO_PASSWORD_${node_id}"
node_control="BOOTSTRAP_ANSIBLE_CONTROL_NODE_${node_id}"
node_hostname="BOOTSTRAP_ANSIBLE_HOSTNAME_${node_id}"
_has_envar "${node_addr}"
_has_envar "${node_username}"
_has_envar "${node_password}" "true"
_has_envar "${node_control}"
_has_optional_envar "${node_hostname}"
if [[ "${!node_addr}" == "${BOOTSTRAP_KUBE_VIP_ADDR}" && "${BOOTSTRAP_KUBE_VIP_ENABLED}" == "true" ]]; then
_log "ERROR(${FUNCNAME[0]})" "The kube-vip IP '${BOOTSTRAP_KUBE_VIP_ADDR}' should not be the same as the IP for node '${!node_addr}'"
exit 1
fi
if [[ "${!node_addr}" == "${BOOTSTRAP_METALLB_K8S_GATEWAY_ADDR}" ]]; then
_log "ERROR(${FUNCNAME[0]})" "The k8s-gateway load balancer IP '${BOOTSTRAP_METALLB_K8S_GATEWAY_ADDR}' should not be the same as the IP for node '${!node_addr}'"
exit 1
fi
if [[ "${!node_addr}" == "${BOOTSTRAP_METALLB_INGRESS_ADDR}" ]]; then
_log "ERROR(${FUNCNAME[0]})" "The ingress load balancer IP '${BOOTSTRAP_METALLB_INGRESS_ADDR}' should not be the same as the IP for node '${!node_addr}'"
exit 1
fi
if ssh -q -o BatchMode=yes -o ConnectTimeout=5 "${!node_username}"@"${!var}" "true"; then
_log "INFO(${FUNCNAME[0]})" "SSH into host '${!var}' with username '${!node_username}' was successfull"
else
_log "ERROR(${FUNCNAME[0]})" "SSH into host '${!var}' with username '${!node_username}'was NOT successful, did you copy over your SSH key?"
exit 1
fi
done
}
verify_start() {
_log "INFO(${FUNCNAME[0]})" "Starting verification of .config.env, please wait..."
}
verify_success() {
_log "INFO(${FUNCNAME[0]})" "All checks passed!"
_log "INFO(${FUNCNAME[0]})" "Run the script without --verify to template all the files out"
exit 0
}
generate_ansible_host_secrets() {
local node_id=
local node_username=
local node_password=
local node_hostname=
local node_control=
default_control_node_prefix=${BOOTSTRAP_ANSIBLE_DEFAULT_CONTROL_NODE_HOSTNAME_PREFIX:-k8s-}
default_worker_node_prefix=${BOOTSTRAP_ANSIBLE_DEFAULT_NODE_HOSTNAME_PREFIX:-k8s-}
for var in "${!BOOTSTRAP_ANSIBLE_HOST_ADDR_@}"; do
node_id=$(echo "${var}" | awk -F"_" '{print $5}')
node_control="BOOTSTRAP_ANSIBLE_CONTROL_NODE_${node_id}"
if [[ "${!node_control}" == "true" ]]; then
node_hostname="BOOTSTRAP_ANSIBLE_HOSTNAME_${node_id}"
host_key="${!node_hostname:-${default_control_node_prefix}}"
if [ "${host_key}" == "${default_control_node_prefix}" ]; then
node_hostname=${default_control_node_prefix}${node_id}
else
node_hostname=${!node_hostname}
fi
else
node_hostname="BOOTSTRAP_ANSIBLE_HOSTNAME_${node_id}"
host_key="${!node_hostname:-${default_worker_node_prefix}}"
if [ "${host_key}" == "${default_worker_node_prefix}" ]; then
node_hostname=${default_worker_node_prefix}${node_id}
else
node_hostname=${!node_hostname}
fi
fi
{
node_username="BOOTSTRAP_ANSIBLE_SSH_USERNAME_${node_id}"
node_password="BOOTSTRAP_ANSIBLE_SUDO_PASSWORD_${node_id}"
printf "kind: Secret\n"
printf "ansible_user: %s\n" "${!node_username}"
printf "ansible_become_pass: %s\n" "${!node_password}"
} > "${PROJECT_DIR}/ansible/inventory/host_vars/${node_hostname}.sops.yml"
sops --encrypt --in-place "${PROJECT_DIR}/ansible/inventory/host_vars/${node_hostname}.sops.yml"
done
}
generate_ansible_hosts() {
local worker_node_count=
default_control_node_prefix=${BOOTSTRAP_ANSIBLE_DEFAULT_CONTROL_NODE_HOSTNAME_PREFIX:-k8s-}
default_worker_node_prefix=${BOOTSTRAP_ANSIBLE_DEFAULT_NODE_HOSTNAME_PREFIX:-k8s-}
{
printf -- "---\n"
printf "kubernetes:\n"
printf " children:\n"
printf " master:\n"
printf " hosts:\n"
master_node_count=0
worker_node_count=0
for var in "${!BOOTSTRAP_ANSIBLE_HOST_ADDR_@}"; do
node_id=$(echo "${var}" | awk -F"_" '{print $5}')
node_control="BOOTSTRAP_ANSIBLE_CONTROL_NODE_${node_id}"
if [[ "${!node_control}" == "true" ]]; then
master_node_count=$((master_node_count+1))
node_hostname="BOOTSTRAP_ANSIBLE_HOSTNAME_${node_id}"
host_key="${!node_hostname:-${default_control_node_prefix}}"
if [ "${host_key}" == "${default_control_node_prefix}" ]; then
node_hostname=${default_control_node_prefix}${node_id}
else
node_hostname=${!node_hostname}
fi
printf " %s:\n" "${node_hostname}"
printf " ansible_host: %s\n" "${!var}"
else
worker_node_count=$((worker_node_count+1))
fi
done
if [[ ${worker_node_count} -gt 0 ]]; then
printf " worker:\n"
printf " hosts:\n"
for var in "${!BOOTSTRAP_ANSIBLE_HOST_ADDR_@}"; do
node_id=$(echo "${var}" | awk -F"_" '{print $5}')
node_control="BOOTSTRAP_ANSIBLE_CONTROL_NODE_${node_id}"
if [[ "${!node_control}" == "false" ]]; then
node_hostname="BOOTSTRAP_ANSIBLE_HOSTNAME_${node_id}"
host_key="${!node_hostname:-${default_worker_node_prefix}}"
if [ "${host_key}" == "${default_worker_node_prefix}" ]; then
node_hostname=${default_worker_node_prefix}${node_id}
else
node_hostname=${!node_hostname}
fi
printf " %s:\n" "${node_hostname}"
printf " ansible_host: %s\n" "${!var}"
fi
done
fi
} > "${PROJECT_DIR}/ansible/inventory/hosts.yml"
}
setup_prometheus_endpoints() {
yq --inplace 'del(.spec.values.kubeControllerManager.endpoints[])' \
"${PROJECT_DIR}/kubernetes/apps/monitoring/kube-prometheus-stack/app/helmrelease.yaml"
for var in "${!BOOTSTRAP_ANSIBLE_HOST_ADDR_@}"; do
node_id=$(echo "${var}" | awk -F"_" '{print $5}')
node_control="BOOTSTRAP_ANSIBLE_CONTROL_NODE_${node_id}"
if [[ "${!node_control}" == "true" ]]; then
node_addr="BOOTSTRAP_ANSIBLE_HOST_ADDR_${node_id}"
_log "INFO(${FUNCNAME[0]})" "Setting up Prometheus endpoint for '${!node_addr}'"
yq --inplace ".spec.values.kubeControllerManager.endpoints += \"${!node_addr}\"" \
"${PROJECT_DIR}/kubernetes/apps/monitoring/kube-prometheus-stack/app/helmrelease.yaml"
fi
done
}
setup_github_webhook() {
_has_envar "BOOTSTRAP_FLUX_GITHUB_WEBHOOK_SECRET"
WEBHOOK_SECRET="${BOOTSTRAP_FLUX_GITHUB_WEBHOOK_SECRET}"
if [[ "${WEBHOOK_SECRET}" == "generated" ]]; then
WEBHOOK_SECRET="$(openssl rand -hex 12)"
fi
export BOOTSTRAP_FLUX_GITHUB_WEBHOOK_SECRET="${WEBHOOK_SECRET}"
_log "INFO(${FUNCNAME[0]})" "Using GitHub Token '${WEBHOOK_SECRET}' for Flux"
envsubst < "${PROJECT_DIR}/tmpl/kubernetes/github-webhook-token-secret.sops.yaml" \
> "${PROJECT_DIR}/kubernetes/apps/flux-system/addons/webhooks/github/secret.sops.yaml"
sops --encrypt --in-place "${PROJECT_DIR}/kubernetes/apps/flux-system/addons/webhooks/github/secret.sops.yaml"
}
setup_weave_gitops() {
_has_envar "BOOTSTRAP_WEAVE_GITOPS_ADMIN_PASSWORD"
WEAVE_GITOPS_ADMIN_PASSWORD="${BOOTSTRAP_WEAVE_GITOPS_ADMIN_PASSWORD}"
if [[ "${WEAVE_GITOPS_ADMIN_PASSWORD}" == "generated" ]]; then
WEAVE_GITOPS_ADMIN_PASSWORD="$(openssl rand -hex 12)"
fi
export BOOTSTRAP_WEAVE_GITOPS_ADMIN_PASSWORD="${WEAVE_GITOPS_ADMIN_PASSWORD}"
_log "INFO(${FUNCNAME[0]})" "Using admin password '${WEAVE_GITOPS_ADMIN_PASSWORD}' for Weave Gitops"
# Convert password to bcrypt hash
# shellcheck disable=SC2155
export BOOTSTRAP_WEAVE_GITOPS_ADMIN_PASSWORD="$(echo -n "${BOOTSTRAP_WEAVE_GITOPS_ADMIN_PASSWORD}" | gitops get bcrypt-hash)"
envsubst < "${PROJECT_DIR}/tmpl/kubernetes/weave-gitops-secret.sops.yaml" \
> "${PROJECT_DIR}/kubernetes/apps/flux-system/weave-gitops/app/secret.sops.yaml"
sops --encrypt --in-place "${PROJECT_DIR}/kubernetes/apps/flux-system/weave-gitops/app/secret.sops.yaml"
}
setup_grafana_admin() {
_has_envar "BOOTSTRAP_GRAFANA_ADMIN_PASSWORD"
GRAFANA_ADMIN_PASSWORD="${BOOTSTRAP_GRAFANA_ADMIN_PASSWORD}"
if [[ "${GRAFANA_ADMIN_PASSWORD}" == "generated" ]]; then
GRAFANA_ADMIN_PASSWORD="$(openssl rand -hex 12)"
fi
export BOOTSTRAP_GRAFANA_ADMIN_PASSWORD="${GRAFANA_ADMIN_PASSWORD}"
_log "INFO(${FUNCNAME[0]})" "Using password '${GRAFANA_ADMIN_PASSWORD}' for Grafana"
envsubst < "${PROJECT_DIR}/tmpl/kubernetes/grafana-admin-secret.sops.yaml" \
> "${PROJECT_DIR}/kubernetes/apps/monitoring/grafana/app/secret.sops.yaml"
sops --encrypt --in-place "${PROJECT_DIR}/kubernetes/apps/monitoring/grafana/app/secret.sops.yaml"
}
success() {
_log "INFO(${FUNCNAME[0]})" "All files have been templated, proceed to the next steps outlined in the README"
exit 0
}
_log() {
local type="${1}"
local msg="${2}"
printf 'timestamp="%s" type="%s" message="%s"\n' "$(date)" "${type}" "${msg}"
}
main "$@"