Files
it-ansible/add-service.sh

148 lines
3.6 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
APPS_DIR="${ROOT_DIR}/docker_compose_applications"
INVENTORY_FILE="${ROOT_DIR}/inventories/hetzner/host_vars/cit-docker-host.yaml"
log() {
printf '[add-service] %s\n' "$*"
}
die() {
printf '[add-service] ERROR: %s\n' "$*" >&2
exit 1
}
usage() {
cat <<EOF
Usage: $(basename "$0") <github-ssh-uri|service-name> [service-name]
Examples:
$(basename "$0") git@github.com:example/repo.git
$(basename "$0") git@github.com:example/repo.git custom-name
$(basename "$0") my-new-service
When a GitHub SSH URI is provided, the repo is cloned into docker_compose_applications/
and the inventory is updated. When plain text is provided, a scaffold folder with a
compose.yaml template is created and the inventory is updated.
EOF
exit 1
}
require_cmd() {
command -v "$1" >/dev/null 2>&1 || die "Missing required command: $1"
}
ensure_paths() {
[ -d "$APPS_DIR" ] || mkdir -p "$APPS_DIR"
[ -f "$INVENTORY_FILE" ] || die "services list $INVENTORY_FILE not found"
}
is_github_ssh_uri() {
[[ "$1" =~ ^git@github\.com:.+\.git$ ]]
}
sanitize_name() {
local raw="$1"
local clean
clean="$(printf '%s' "$raw" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9]+/-/g; s/^-+//; s/-+$//; s/-+/-/g')"
[ -n "$clean" ] || die "Service name resolved to empty after sanitizing"
printf '%s' "$clean"
}
service_in_inventory() {
local name="$1"
grep -Eq "^[[:space:]]+- name: ${name}$" "$INVENTORY_FILE"
}
append_inventory_entry() {
local name="$1"
local dir_name="$2"
if service_in_inventory "$name"; then
die "Service '${name}' already present in inventory"
fi
{
printf '\n - name: %s\n' "$name"
printf ' files_directory: ../docker_compose_applications/%s\n' "$dir_name"
} >>"$INVENTORY_FILE"
log "Added '${name}' to inventory"
}
derive_name_from_uri() {
local uri="$1"
local repo="${uri##*/}"
repo="${repo%.git}"
sanitize_name "$repo"
}
clone_repo() {
local uri="$1"
local target_dir="$2"
[ -e "$target_dir" ] && die "Target directory already exists: $target_dir"
require_cmd git
log "Cloning ${uri} into ${target_dir}"
git clone --depth=1 "$uri" "$target_dir"
}
create_compose_template() {
local dir="$1"
local service_name="$2"
local compose_path="${dir}/compose.yaml"
[ -e "$compose_path" ] && die "compose.yaml already exists at ${compose_path}"
cat >"$compose_path" <<EOF
services:
${service_name}:
image: replace-me
container_name: ${service_name}
restart: unless-stopped
networks:
- caddy_net
networks:
caddy_net:
external: true
EOF
log "Created compose template at ${compose_path}"
}
create_scaffold() {
local dir="$1"
local service_name="$2"
[ -e "$dir" ] && die "Target directory already exists: $dir"
mkdir -p "$dir"
create_compose_template "$dir" "$service_name"
}
main() {
local input="${1:-}"
local override_name="${2:-}"
[ -n "$input" ] || usage
ensure_paths
if is_github_ssh_uri "$input"; then
local service_name="${override_name:-$(derive_name_from_uri "$input")}"
local target_dir="${APPS_DIR}/${service_name}"
clone_repo "$input" "$target_dir"
append_inventory_entry "$service_name" "$service_name"
log "Service '${service_name}' ready from GitHub source"
else
local service_name="${override_name:-$(sanitize_name "$input")}"
local target_dir="${APPS_DIR}/${service_name}"
create_scaffold "$target_dir" "$service_name"
append_inventory_entry "$service_name" "$service_name"
log "Service '${service_name}' scaffolded locally"
fi
}
main "$@"