mirror of
https://github.com/openclaw/openclaw.git
synced 2026-10-03 17:53:39 +00:00
Consolidate repeated tooling flows while preserving command contracts. Fix swallowed HTML translation errors and browser-realm error handling in the Google Live smoke. Owner tests and CLI parity passed on Testbox; final broad gate replay follows a fixture lint correction.
164 lines
5 KiB
Bash
Executable file
164 lines
5 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# Bash 5.3+ can deadlock writing heredoc pipes on macOS before the reader starts.
|
|
if [[ ${OSTYPE:-} == darwin* && $BASH != /bin/bash ]] && ((BASH_VERSINFO[0] > 5 || (BASH_VERSINFO[0] == 5 && BASH_VERSINFO[1] >= 3))); then
|
|
exec /bin/bash "$0" "$@"
|
|
fi
|
|
# Bootstrap a local Kind cluster.
|
|
# Usage:
|
|
# ./scripts/k8s/create-kind.sh # Create with auto-detected engine
|
|
# ./scripts/k8s/create-kind.sh --name mycluster
|
|
# ./scripts/k8s/create-kind.sh --delete
|
|
#
|
|
# After creation, deploy with:
|
|
# export <AI_PROVIDER>_API_KEY="..." && ./scripts/k8s/deploy.sh
|
|
|
|
set -euo pipefail
|
|
|
|
CLUSTER_NAME="openclaw"
|
|
CONTAINER_CMD=""
|
|
DELETE=false
|
|
|
|
GREEN='\033[0;32m'
|
|
BLUE='\033[0;34m'
|
|
YELLOW='\033[0;33m'
|
|
RED='\033[0;31m'
|
|
NC='\033[0m'
|
|
|
|
info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
|
success() { echo -e "${GREEN}[OK]${NC} $1"; }
|
|
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
|
fail() { echo -e "${RED}[ERROR]${NC} $1" >&2; exit 1; }
|
|
|
|
usage() {
|
|
cat <<EOF
|
|
Usage: $(basename "$0") [OPTIONS]
|
|
|
|
|
|
Options:
|
|
--name NAME Cluster name (default: openclaw)
|
|
--delete Delete the cluster instead of creating it
|
|
-h, --help Show this help message
|
|
|
|
Examples:
|
|
$(basename "$0") # Create cluster (auto-detect engine)
|
|
$(basename "$0") --delete # Delete the cluster
|
|
$(basename "$0") --name dev --delete # Delete a cluster named "dev"
|
|
EOF
|
|
exit 0
|
|
}
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--name)
|
|
[[ -z "${2:-}" ]] && fail "--name requires a value"
|
|
CLUSTER_NAME="$2"; shift 2 ;;
|
|
--delete)
|
|
DELETE=true; shift ;;
|
|
-h|--help)
|
|
usage ;;
|
|
*)
|
|
fail "Unknown option: $1 (see --help)" ;;
|
|
esac
|
|
done
|
|
|
|
detect_provider() {
|
|
local candidate
|
|
|
|
for candidate in podman docker; do
|
|
if command -v "$candidate" &>/dev/null && "$candidate" info &>/dev/null; then
|
|
echo "$candidate"
|
|
return 0
|
|
fi
|
|
done
|
|
|
|
for candidate in podman docker; do
|
|
if command -v "$candidate" &>/dev/null; then
|
|
case "$candidate" in
|
|
podman)
|
|
fail "Podman is installed but not responding, and no responsive Docker daemon was found. Ensure the podman machine is running (podman machine start) or start Docker."
|
|
;;
|
|
docker)
|
|
fail "Docker is installed but not running, and no responsive Podman machine was found. Start Docker or start Podman."
|
|
;;
|
|
esac
|
|
fi
|
|
done
|
|
|
|
fail "Neither podman nor docker found. Install one to use Kind."
|
|
}
|
|
|
|
CONTAINER_CMD=$(detect_provider)
|
|
info "Auto-detected container engine: $CONTAINER_CMD"
|
|
|
|
if ! command -v kind &>/dev/null; then
|
|
fail "kind is not installed. Install it from https://kind.sigs.k8s.io/"
|
|
fi
|
|
|
|
if ! command -v kubectl &>/dev/null; then
|
|
fail "kubectl is not installed. Install it before creating or managing a Kind cluster."
|
|
fi
|
|
|
|
if ! "$CONTAINER_CMD" info &>/dev/null; then
|
|
if [[ "$CONTAINER_CMD" == "docker" ]]; then
|
|
fail "Docker daemon is not running. Start it and try again."
|
|
elif [[ "$CONTAINER_CMD" == "podman" ]]; then
|
|
fail "Podman is not responding. Ensure the podman machine is running (podman machine start)."
|
|
fi
|
|
fi
|
|
|
|
if $DELETE; then
|
|
info "Deleting Kind cluster '$CLUSTER_NAME'..."
|
|
if KIND_EXPERIMENTAL_PROVIDER="$CONTAINER_CMD" kind get clusters 2>/dev/null | grep -qx "$CLUSTER_NAME"; then
|
|
KIND_EXPERIMENTAL_PROVIDER="$CONTAINER_CMD" kind delete cluster --name "$CLUSTER_NAME"
|
|
success "Cluster '$CLUSTER_NAME' deleted."
|
|
else
|
|
warn "Cluster '$CLUSTER_NAME' does not exist."
|
|
fi
|
|
exit 0
|
|
fi
|
|
|
|
if KIND_EXPERIMENTAL_PROVIDER="$CONTAINER_CMD" kind get clusters 2>/dev/null | grep -qx "$CLUSTER_NAME"; then
|
|
warn "Cluster '$CLUSTER_NAME' already exists."
|
|
info "To recreate it, run: $0 --name \"$CLUSTER_NAME\" --delete && $0 --name \"$CLUSTER_NAME\""
|
|
info "Switching kubectl context to kind-$CLUSTER_NAME..."
|
|
kubectl config use-context "kind-$CLUSTER_NAME" &>/dev/null && success "Context set." || warn "Could not switch context."
|
|
exit 0
|
|
fi
|
|
|
|
info "Creating Kind cluster '$CLUSTER_NAME' (provider: $CONTAINER_CMD)..."
|
|
|
|
KIND_EXPERIMENTAL_PROVIDER="$CONTAINER_CMD" kind create cluster \
|
|
--name "$CLUSTER_NAME" \
|
|
--config - <<'KINDCFG'
|
|
kind: Cluster
|
|
apiVersion: kind.x-k8s.io/v1alpha4
|
|
nodes:
|
|
- role: control-plane
|
|
labels:
|
|
openclaw.dev/role: control-plane
|
|
# Uncomment to expose services on host ports:
|
|
# extraPortMappings:
|
|
# - containerPort: 30080
|
|
# hostPort: 8080
|
|
# protocol: TCP
|
|
# - containerPort: 30443
|
|
# hostPort: 8443
|
|
# protocol: TCP
|
|
KINDCFG
|
|
|
|
success "Kind cluster '$CLUSTER_NAME' created."
|
|
|
|
info "Waiting for cluster to be ready..."
|
|
kubectl --context "kind-$CLUSTER_NAME" wait --for=condition=Ready nodes --all --timeout=120s >/dev/null
|
|
success "All nodes are Ready."
|
|
|
|
echo ""
|
|
echo "---------------------------------------------------------------"
|
|
echo " Kind cluster '$CLUSTER_NAME' is ready"
|
|
echo "---------------------------------------------------------------"
|
|
echo ""
|
|
echo " kubectl cluster-info --context kind-$CLUSTER_NAME"
|
|
echo ""
|
|
echo ""
|
|
echo " export <AI_PROVIDER>_API_KEY=\"...\" && ./scripts/k8s/deploy.sh"
|
|
echo ""
|