Files
beaver_project/app-instance/remove-instance.sh
2026-03-13 16:40:08 +08:00

131 lines
3.4 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REGISTRY_TOOL="${SCRIPT_DIR}/instance-registry.py"
REGISTRY_PATH_DEFAULT="${SCRIPT_DIR}/runtime/registry/instances.json"
INSTANCE_ID=""
INSTANCE_SLUG=""
CONTAINER_NAME=""
REGISTRY_PATH="${REGISTRY_PATH:-$REGISTRY_PATH_DEFAULT}"
PURGE_DATA=0
usage() {
cat <<'EOF'
Usage:
./remove-instance.sh [--instance-id <id> | --slug <slug> | --container-name <name>] [options]
Options:
--instance-id <id> Remove by instance id.
--slug <slug> Remove by instance slug.
--container-name <name> Remove by container name.
--purge-data Delete instance data directory after container removal.
--registry <path> Registry JSON path.
--help Show this help.
EOF
}
log() {
printf '[remove-instance] %s\n' "$*"
}
die() {
printf '[remove-instance] %s\n' "$*" >&2
exit 1
}
purge_instance_root() {
local instance_root="$1"
local image_name="$2"
[[ -d "$instance_root" ]] || return 0
docker run --rm \
-v "${instance_root}:/target" \
--entrypoint /bin/sh \
"$image_name" \
-c 'rm -rf /target/* /target/.[!.]* /target/..?*' >/dev/null
rmdir "$instance_root"
}
while [[ $# -gt 0 ]]; do
case "$1" in
--instance-id)
INSTANCE_ID="${2:-}"
shift 2
;;
--slug)
INSTANCE_SLUG="${2:-}"
shift 2
;;
--container-name)
CONTAINER_NAME="${2:-}"
shift 2
;;
--registry)
REGISTRY_PATH="${2:-}"
shift 2
;;
--purge-data)
PURGE_DATA=1
shift
;;
--help|-h)
usage
exit 0
;;
*)
die "unknown argument: $1"
;;
esac
done
if [[ -z "$INSTANCE_ID$INSTANCE_SLUG$CONTAINER_NAME" ]]; then
die "one of --instance-id, --slug or --container-name is required"
fi
REGISTRY_GET_ARGS=(--registry "$REGISTRY_PATH" get)
if [[ -n "$INSTANCE_ID" ]]; then
REGISTRY_GET_ARGS+=(--instance-id "$INSTANCE_ID")
fi
if [[ -n "$INSTANCE_SLUG" ]]; then
REGISTRY_GET_ARGS+=(--slug "$INSTANCE_SLUG")
fi
if [[ -n "$CONTAINER_NAME" ]]; then
REGISTRY_GET_ARGS+=(--container-name "$CONTAINER_NAME")
fi
if ! RECORD_JSON="$("$REGISTRY_TOOL" "${REGISTRY_GET_ARGS[@]}" 2>/dev/null)"; then
die "instance not found in registry"
fi
INSTANCE_ID="$(printf '%s' "$RECORD_JSON" | python3 -c 'import json,sys; print(json.load(sys.stdin)["instance_id"])')"
INSTANCE_SLUG="$(printf '%s' "$RECORD_JSON" | python3 -c 'import json,sys; print(json.load(sys.stdin)["instance_slug"])')"
CONTAINER_NAME="$(printf '%s' "$RECORD_JSON" | python3 -c 'import json,sys; print(json.load(sys.stdin)["container_name"])')"
INSTANCE_ROOT="$(printf '%s' "$RECORD_JSON" | python3 -c 'import json,sys; print(json.load(sys.stdin)["instance_root"])')"
IMAGE_NAME="$(printf '%s' "$RECORD_JSON" | python3 -c 'import json,sys; print(json.load(sys.stdin)["image_name"])')"
if docker container inspect "$CONTAINER_NAME" >/dev/null 2>&1; then
log "removing container ${CONTAINER_NAME}"
docker rm -f "$CONTAINER_NAME" >/dev/null
else
log "container ${CONTAINER_NAME} already absent"
fi
"$REGISTRY_TOOL" --registry "$REGISTRY_PATH" remove --instance-id "$INSTANCE_ID" >/dev/null
if [[ "$PURGE_DATA" -eq 1 ]]; then
log "purging instance data ${INSTANCE_ROOT}"
purge_instance_root "$INSTANCE_ROOT" "$IMAGE_NAME"
fi
cat <<EOF
instance_id=${INSTANCE_ID}
instance_slug=${INSTANCE_SLUG}
container_name=${CONTAINER_NAME}
instance_root=${INSTANCE_ROOT}
purged_data=${PURGE_DATA}
EOF