#!/usr/bin/env bash set -euo pipefail NAMESPACE="${NAMESPACE:-pcp-dev}" POSTGRES_SERVICE="${POSTGRES_SERVICE:-pcp-postgres}" CLUSTER_DOMAIN="${CLUSTER_DOMAIN:-altum.local}" POSTGRES_IMAGE="${POSTGRES_IMAGE:-postgis/postgis:15-3.3}" ADMIN_SECRET="${ADMIN_SECRET:-pcp-postgres-admin}" ADMIN_PASSWORD_KEY="${ADMIN_PASSWORD_KEY:-POSTGRES_PASSWORD}" POSTGRES_HOST="${POSTGRES_SERVICE}.${NAMESPACE}.svc.${CLUSTER_DOMAIN}" usage() { cat < [db_name...] $0 -f databases.txt Examples: $0 pcp_satellite_catalog pcp_ballistics cat > databases.txt </dev/null 2>&1; then echo "ERROR: required command not found: $1" >&2 exit 1 fi } validate_db_name() { local db_name="$1" if [[ ! "$db_name" =~ ^[a-z][a-z0-9_]*$ ]]; then echo "ERROR: invalid database name: $db_name" >&2 echo "Allowed format: lowercase letters, digits, underscore; must start with a letter." >&2 exit 1 fi } secret_name_for_db() { local db_name="$1" local dashed="${db_name//_/-}" echo "${dashed}-db" } user_name_for_db() { local db_name="$1" echo "${db_name}_user" } make_pod_name() { local prefix="$1" local db_name="$2" local safe="${db_name//_/-}" safe="${safe:0:35}" echo "${prefix}-${safe}-${RANDOM}${RANDOM}" } get_admin_password() { kubectl -n "$NAMESPACE" get secret "$ADMIN_SECRET" \ -o jsonpath="{.data.${ADMIN_PASSWORD_KEY}}" | base64 -d } get_or_create_service_password() { local secret_name="$1" if kubectl -n "$NAMESPACE" get secret "$secret_name" >/dev/null 2>&1; then kubectl -n "$NAMESPACE" get secret "$secret_name" \ -o jsonpath='{.data.SPRING_DATASOURCE_PASSWORD}' | base64 -d else openssl rand -base64 32 | tr -d '/+=' | head -c 32 fi } create_database_and_user() { local db_name="$1" local db_user="$2" local db_password="$3" local admin_password="$4" local pod_name pod_name="$(make_pod_name "psql-create" "$db_name")" echo "Creating/updating database and user:" echo " database: $db_name" echo " user: $db_user" kubectl -n "$NAMESPACE" run --rm -i "$pod_name" \ --image="$POSTGRES_IMAGE" \ --restart=Never \ --env="PGPASSWORD=$admin_password" \ --command -- psql \ -h "$POSTGRES_HOST" \ -U postgres \ -d postgres <&2 exit 1 fi local file="$2" if [[ ! -f "$file" ]]; then echo "ERROR: file not found: $file" >&2 exit 1 fi grep -vE '^\s*($|#)' "$file" else printf '%s\n' "$@" fi } main() { require_command kubectl require_command openssl require_command base64 echo "Namespace: $NAMESPACE" echo "Postgres host: $POSTGRES_HOST" echo "Postgres image: $POSTGRES_IMAGE" echo "Admin secret: $ADMIN_SECRET" echo local admin_password admin_password="$(get_admin_password)" mapfile -t databases < <(read_db_list "$@") if [[ "${#databases[@]}" -eq 0 ]]; then echo "ERROR: database list is empty" >&2 exit 1 fi for db_name in "${databases[@]}"; do validate_db_name "$db_name" local db_user local secret_name local db_password local jdbc_url db_user="$(user_name_for_db "$db_name")" secret_name="$(secret_name_for_db "$db_name")" db_password="$(get_or_create_service_password "$secret_name")" jdbc_url="jdbc:postgresql://${POSTGRES_HOST}:5432/${db_name}" echo echo "============================================================" echo "Processing database: $db_name" echo "============================================================" create_database_and_user "$db_name" "$db_user" "$db_password" "$admin_password" enable_postgis "$db_name" "$db_user" "$admin_password" create_or_update_secret "$db_name" "$db_user" "$db_password" "$secret_name" check_database "$db_name" "$db_user" "$db_password" echo echo "Done:" echo " database: $db_name" echo " user: $db_user" echo " secret: $secret_name" echo " JDBC URL: $jdbc_url" done echo echo "All databases processed successfully." } main "$@"