Files
wild-cloud/bin/wild-app-deploy

171 lines
5.7 KiB
Bash
Executable File

#!/bin/bash
set -e
FORCE=false
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
--force)
FORCE=true
shift
;;
--dry-run)
DRY_RUN="--dry-run=client"
shift
;;
-*)
echo "Unknown option $1"
echo "Usage: $0 <app_name> [--force] [--dry-run]"
exit 1
;;
*)
if [ -z "${APP_NAME}" ]; then
APP_NAME="$1"
else
echo "Too many arguments"
echo "Usage: $0 <app_name> [--force] [--dry-run]"
exit 1
fi
shift
;;
esac
done
if [ -z "${APP_NAME}" ]; then
echo "Usage: $0 <app_name> [--force] [--dry-run]"
exit 1
fi
if [ ! -d "apps/${APP_NAME}" ]; then
echo "Error: App directory 'apps/${APP_NAME}' not found"
exit 1
fi
# Initialize Wild Cloud environment
if [ -z "${WC_ROOT}" ]; then
print "WC_ROOT is not set."
exit 1
else
source "${WC_ROOT}/scripts/common.sh"
init_wild_env
fi
SECRETS_FILE="${WC_HOME}/secrets.yaml"
if [ ! -f "${SECRETS_FILE}" ]; then
echo "Error: Secrets file '${SECRETS_FILE}' not found"
exit 1
fi
# Function to deploy secrets for an app
deploy_secrets() {
local app_name="$1"
local target_namespace="${2:-${app_name}}" # Default to app name if not specified
# Check if app has a manifest with requiredSecrets
local manifest_file="apps/${app_name}/manifest.yaml"
if [ ! -f "${manifest_file}" ]; then
return 0
fi
# Check if there are required secrets defined
if ! yq eval '.requiredSecrets' "${manifest_file}" | grep -q -v '^null$'; then
return 0
fi
# Use the target namespace parameter
local namespace="${target_namespace}"
echo "Deploying secrets for app '${app_name}' in namespace '${namespace}'"
# Gather data for app secret
local secret_data=""
while IFS= read -r secret_path; do
secret_value=$(yq eval ".${secret_path} // \"\"" "${SECRETS_FILE}")
if [ -n "${secret_value}" ] && [ "${secret_value}" != "null" ]; then
secret_data="${secret_data} --from-literal=${secret_path}=${secret_value}"
else
echo "Error: Required secret '${secret_path}' not found in ${SECRETS_FILE} for app '${app_name}'"
exit 1
fi
done < <(yq eval '.requiredSecrets[]' "${manifest_file}")
# Create/update app secret in cluster
if [ -n "${secret_data}" ]; then
echo "Creating/updating secret '${app_name}-secrets' in namespace '${namespace}'"
if [ "${DRY_RUN:-}" = "--dry-run=client" ]; then
echo "DRY RUN: kubectl create secret generic ${app_name}-secrets ${secret_data} --namespace=${namespace} --dry-run=client -o yaml"
else
kubectl delete secret "${app_name}-secrets" --namespace="${namespace}" --ignore-not-found=true
kubectl create secret generic "${app_name}-secrets" ${secret_data} --namespace="${namespace}"
fi
fi
}
# Step 1: Create namespaces first
echo "Creating namespaces..."
MANIFEST_FILE="apps/${APP_NAME}/manifest.yaml"
# Create dependency namespaces.
if [ -f "${MANIFEST_FILE}" ]; then
if yq eval '.requires' "${MANIFEST_FILE}" | grep -q -v '^null$'; then
yq eval '.requires[].name' "${MANIFEST_FILE}" | while read -r required_app; do
if [ -z "${required_app}" ] || [ "${required_app}" = "null" ]; then
echo "Warning: Empty or null dependency found, skipping"
continue
fi
if [ ! -d "apps/${required_app}" ]; then
echo "Error: Required dependency '${required_app}' not found in apps/ directory"
exit 1
fi
if [ -f "apps/${required_app}/namespace.yaml" ]; then
echo "Creating namespace for dependency: ${required_app}"
kubectl apply -f "apps/${required_app}/namespace.yaml" ${DRY_RUN:-}
else
echo "Warning: No namespace.yaml found for dependency: ${required_app}"
fi
done
fi
fi
# Create namespace for main app
if [ -f "apps/${APP_NAME}/namespace.yaml" ]; then
echo "Creating namespace for app: ${APP_NAME}"
kubectl apply -f "apps/${APP_NAME}/namespace.yaml" ${DRY_RUN:-}
fi
# Copy TLS certificates to the namespace
if [ -f "apps/${APP_NAME}/namespace.yaml" ]; then
NAMESPACE=$(yq eval '.metadata.name' "apps/${APP_NAME}/namespace.yaml")
echo "Step 3: Copying TLS certificates to namespace $NAMESPACE..."
wild-cluster-secret-copy cert-manager:wildcard-internal-wild-cloud-tls "$NAMESPACE" || echo "Warning: Failed to copy internal wildcard certificate"
wild-cluster-secret-copy cert-manager:wildcard-wild-cloud-tls "$NAMESPACE" || echo "Warning: Failed to copy external wildcard certificate"
fi
# Deploy secrets for this app
deploy_secrets "${APP_NAME}"
# Step 2.5: Handle idempotent jobs (delete and recreate)
echo "Managing idempotent jobs..."
if [ -f "apps/${APP_NAME}/db-init-job.yaml" ]; then
echo "Deleting and recreating db-init job for idempotent execution"
kubectl delete job immich-db-init --namespace="${APP_NAME}" --ignore-not-found=true ${DRY_RUN:-}
# Wait for job deletion to complete
if [ "${DRY_RUN:-}" != "--dry-run=client" ]; then
kubectl wait --for=delete job/immich-db-init --namespace="${APP_NAME}" --timeout=30s || true
fi
fi
# Step 3: Deploy the main application
echo "Deploying application..."
if [ "${FORCE}" = true ]; then
echo "Force deploying app '${APP_NAME}'"
kubectl replace --force -k "apps/${APP_NAME}" ${DRY_RUN:-}
else
echo "Deploying app '${APP_NAME}'"
kubectl apply -k "apps/${APP_NAME}" ${DRY_RUN:-}
fi