Files
kubernetes/init-app.sh

160 lines
6.4 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# init-app.sh
# Creates clusters/<cluster>/apps/<application>, renders templates (APPLICATION_NAME, DESCRIPTION, CLUSTER_NAME),
# appends the app to the end of the parent clusters/<cluster>/apps/kustomization.yaml list (removing trailing blank line if present),
# creates a placeholder under manifests/<cluster>/<application>,
# and stages changes in Git (including the placeholder file).
set -euo pipefail
resolve_script_dir() {
local src="${BASH_SOURCE[0]:-$0}"
while [ -h "$src" ]; do
local dir
dir="$(cd -P "$(dirname "$src")" && pwd)"
src="$(readlink "$src")"
[[ "$src" != /* ]] && src="$dir/$src"
done
cd -P "$(dirname "$src")" >/dev/null 2>&1
pwd
}
SCRIPT_DIR="$(resolve_script_dir)"
# Application name
read -r -p "Application name (lowercase, letters/numbers/dashes): " APPLICATION_NAME
APPLICATION_NAME="$(echo "$APPLICATION_NAME" | awk '{$1=$1;print}')"
if [[ -z "$APPLICATION_NAME" ]]; then
echo "Error: Application name cannot be empty." >&2; exit 1
fi
if ! [[ "$APPLICATION_NAME" =~ ^[a-z0-9-]+$ ]]; then
echo "Error: Application name must be lowercase and contain only letters (az), numbers (09), or dashes (-)." >&2; exit 1
fi
if [[ "$APPLICATION_NAME" == *"/"* || "$APPLICATION_NAME" == *"\\"* ]]; then
echo "Error: Application name must not contain path separators (/ or \\)." >&2; exit 1
fi
# Cluster name
DEFAULT_CLUSTER="artemis"
read -r -p "Cluster name [${DEFAULT_CLUSTER}] (lowercase, letters/numbers/dashes): " CLUSTER_NAME
CLUSTER_NAME="${CLUSTER_NAME:-$DEFAULT_CLUSTER}"
CLUSTER_NAME="$(echo "$CLUSTER_NAME" | awk '{$1=$1;print}')"
if [[ -z "$CLUSTER_NAME" ]]; then
echo "Error: Cluster name cannot be empty." >&2; exit 1
fi
if ! [[ "$CLUSTER_NAME" =~ ^[a-z0-9-]+$ ]]; then
echo "Error: Cluster name must be lowercase and contain only letters (az), numbers (09), or dashes (-)." >&2; exit 1
fi
if [[ "$CLUSTER_NAME" == *"/"* || "$CLUSTER_NAME" == *"\\"* ]]; then
echo "Error: Cluster name must not contain path separators (/ or \\)." >&2; exit 1
fi
# Description
read -r -p "Description (spaces, letters, numbers, dots, commas): " DESCRIPTION
DESCRIPTION="$(echo "$DESCRIPTION" | sed 's/^[[:space:]]\+//; s/[[:space:]]\+$//')"
if [ -z "$DESCRIPTION" ]; then
echo "Error: Description cannot be empty." >&2; exit 1
fi
if ! echo "$DESCRIPTION" | grep -Eq '^[A-Za-z0-9 .,]+$'; then
echo "Error: Description may only contain spaces, letters (AZ, az), numbers (09), dots (.), and commas (,)." >&2; exit 1
fi
# Paths
TARGET_DIR="${SCRIPT_DIR}/clusters/${CLUSTER_NAME}/apps/${APPLICATION_NAME}"
MANIFESTS_DIR="${SCRIPT_DIR}/manifests/${CLUSTER_NAME}/${APPLICATION_NAME}"
PARENT_KUSTOMIZATION="${SCRIPT_DIR}/clusters/${CLUSTER_NAME}/apps/kustomization.yaml"
# Abort if clusters target already exists
if [[ -d "$TARGET_DIR" ]]; then
echo "Error: Directory already exists: $TARGET_DIR" >&2; exit 1
fi
# Templates
TEMPLATE_DIR="${SCRIPT_DIR}/.templates"
APP_PROJECT_SRC="${TEMPLATE_DIR}/app-project.yaml"
APPLICATION_SRC="${TEMPLATE_DIR}/application.yaml"
KUSTOMIZATION_SRC="${TEMPLATE_DIR}/kustomization.yaml"
missing=false
for f in "$APP_PROJECT_SRC" "$APPLICATION_SRC" "$KUSTOMIZATION_SRC"; do
if [[ ! -f "$f" ]]; then echo "Error: Template not found: ${f}" >&2; missing=true; fi
done
if [[ "$missing" == true ]]; then exit 1; fi
# Create target directories
mkdir -p "$TARGET_DIR"
mkdir -p "$MANIFESTS_DIR"
# Prepare safe replacements
safe_app_name="${APPLICATION_NAME//\\/\\\\}"; safe_app_name="${safe_app_name//&/\\&}"
safe_description="${DESCRIPTION//\\/\\\\}"; safe_description="${safe_description//&/\\&}"
safe_cluster_name="${CLUSTER_NAME//\\/\\\\}"; safe_cluster_name="${safe_cluster_name//&/\\&}"
# Temp files (init for trap)
tmp1=""; tmp2=""
trap 'rm -f "$tmp1" "$tmp2"' EXIT
# Render app-project.yaml
tmp1="$(mktemp)"
APP_PROJECT_DEST="${TARGET_DIR}/app-project.yaml"
sed -e "s/\${APPLICATION_NAME}/${safe_app_name}/g" \
-e "s/\${DESCRIPTION}/${safe_description}/g" \
"$APP_PROJECT_SRC" > "$tmp1"
mv "$tmp1" "$APP_PROJECT_DEST"
# Render application.yaml (APPLICATION_NAME + CLUSTER_NAME)
tmp2="$(mktemp)"
APPLICATION_DEST="${TARGET_DIR}/application.yaml"
sed -e "s/\${APPLICATION_NAME}/${safe_app_name}/g" \
-e "s/\${CLUSTER_NAME}/${safe_cluster_name}/g" \
"$APPLICATION_SRC" > "$tmp2"
mv "$tmp2" "$APPLICATION_DEST"
# Copy kustomization.yaml as-is
KUSTOMIZATION_DEST="${TARGET_DIR}/kustomization.yaml"
cp "$KUSTOMIZATION_SRC" "$KUSTOMIZATION_DEST"
# Create placeholder in manifests/<cluster>/<application>
PLACEHOLDER_FILE="${MANIFESTS_DIR}/.placeholder"
if [[ ! -f "$PLACEHOLDER_FILE" ]]; then
printf "Placeholder for %s/%s\n" "$CLUSTER_NAME" "$APPLICATION_NAME" > "$PLACEHOLDER_FILE"
fi
echo "Created: $TARGET_DIR"
echo "Wrote: $APP_PROJECT_DEST (APPLICATION_NAME='${APPLICATION_NAME}', DESCRIPTION set)"
echo "Wrote: $APPLICATION_DEST (APPLICATION_NAME='${APPLICATION_NAME}', CLUSTER_NAME='${CLUSTER_NAME}')"
echo "Wrote: $KUSTOMIZATION_DEST (copied as-is)"
echo "Created: $PLACEHOLDER_FILE"
# Parent kustomization.yaml: remove trailing blank line if present, then append new item
if [[ ! -f "$PARENT_KUSTOMIZATION" ]]; then
echo "Error: Parent kustomization not found: ${PARENT_KUSTOMIZATION}" >&2; exit 1
fi
# Remove trailing empty last line (BSD sed)
sed -i '' -e '${/^$/d;}' "$PARENT_KUSTOMIZATION"
# Append the new application entry at end (two-space indent)
printf " - %s\n" "$APPLICATION_NAME" >> "$PARENT_KUSTOMIZATION"
echo "Updated parent kustomization.yaml: appended '${APPLICATION_NAME}' at end of resources list."
# Stage changes in Git (including placeholder file)
if git -C "$SCRIPT_DIR" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
REPO_ROOT="$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel)"
REL_TARGET="${TARGET_DIR#$REPO_ROOT/}"
REL_PARENT="${PARENT_KUSTOMIZATION#$REPO_ROOT/}"
REL_MANIFESTS_DIR="${MANIFESTS_DIR#$REPO_ROOT/}"
REL_PLACEHOLDER="${PLACEHOLDER_FILE#$REPO_ROOT/}"
git -C "$REPO_ROOT" add "$REL_TARGET" "$REL_PARENT" "$REL_MANIFESTS_DIR" "$REL_PLACEHOLDER"
echo "Git: staged new app dir, parent kustomization, manifests dir, and placeholder:"
echo " $REL_TARGET"
echo " $REL_PARENT"
echo " $REL_MANIFESTS_DIR"
echo " $REL_PLACEHOLDER"
echo "Next: commit with a message, e.g.:"
echo " git -C \"$REPO_ROOT\" commit -m \"feat(${CLUSTER_NAME}): add ${APPLICATION_NAME} app (\"${DESCRIPTION}\") and manifests placeholder; update kustomization\""
else
echo "Note: Not inside a Git repository (no .git found). Skipping git add."
fi