Files
kubernetes/init-app.sh

148 lines
5.8 KiB
Bash
Executable File
Raw 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 at the end of the parent clusters/<cluster>/apps/kustomization.yaml list (removing trailing blank line if present),
# and stages changes in Git.
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
TARGET_DIR="${SCRIPT_DIR}/clusters/${CLUSTER_NAME}/apps/${APPLICATION_NAME}"
# Abort if target directory 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 directory
mkdir -p "$TARGET_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"
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)"
# Parent kustomization.yaml: remove trailing blank line if present, then append new item
PARENT_KUSTOMIZATION="${SCRIPT_DIR}/clusters/${CLUSTER_NAME}/apps/kustomization.yaml"
if [[ ! -f "$PARENT_KUSTOMIZATION" ]]; then
echo "Error: Parent kustomization not found: ${PARENT_KUSTOMIZATION}" >&2; exit 1
fi
# 1) If the last line is empty, delete it (BSD sed)
# This prints all lines except a final empty line at EOF.
# Explanation:
# - $: matches the last line
# - /^$/: last line is empty
# - d: delete that line
sed -i '' -e '${/^$/d;}' "$PARENT_KUSTOMIZATION"
# 2) Append the new application line at the end (with two-space indent to match your file)
printf " - %s\n" "$APPLICATION_NAME" >> "$PARENT_KUSTOMIZATION"
echo "Updated parent kustomization.yaml: appended '${APPLICATION_NAME}' at end of resources list."
# Stage changes in Git
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/}"
git -C "$REPO_ROOT" add "$REL_TARGET" "$REL_PARENT"
echo "Git: staged new directory/files and parent kustomization: $REL_TARGET, $REL_PARENT"
echo "Next: commit with a message, e.g.:"
echo " git -C \"$REPO_ROOT\" commit -m \"feat(${CLUSTER_NAME}): add ${APPLICATION_NAME} app (\"${DESCRIPTION}\") and update kustomization\""
else
echo "Note: Not inside a Git repository (no .git found). Skipping git add."
fi