refactor: decompose webdock create_server and koyeb ensure_koyeb_cli into focused helpers (#1016)

webdock/lib/common.sh:
- Extract _webdock_get_public_key_ids() for SSH key ID fetching
- Extract _webdock_validate_inputs() for input validation
- Extract _webdock_handle_create_response() for response parsing and error reporting
- create_server reduced from 53 to 24 lines

koyeb/lib/common.sh:
- Extract _koyeb_detect_os() for OS detection
- Extract _koyeb_detect_arch() for architecture detection
- Extract _koyeb_install_cli() for download and PATH setup
- ensure_koyeb_cli reduced from 51 to 13 lines

Agent: complexity-hunter

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
A 2026-02-13 14:22:24 -08:00 committed by GitHub
parent beec9ab8a3
commit 388770126f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 86 additions and 53 deletions

View file

@ -23,37 +23,36 @@ fi
# Koyeb specific functions
# ============================================================
# Ensure Koyeb CLI is installed
ensure_koyeb_cli() {
if command -v koyeb &>/dev/null; then
log_info "Koyeb CLI available"
return 0
fi
log_step "Installing Koyeb CLI..."
# Detect OS and architecture
local os=""
local arch=""
# Detect OS name for binary downloads (darwin or linux)
# Outputs the OS name to stdout; returns 1 on unsupported OS
_koyeb_detect_os() {
case "$(uname -s)" in
Darwin) os="darwin" ;;
Linux) os="linux" ;;
Darwin) echo "darwin" ;;
Linux) echo "linux" ;;
*)
log_error "Unsupported operating system: $(uname -s)"
return 1
;;
esac
}
# Detect CPU architecture for binary downloads (amd64 or arm64)
# Outputs the arch name to stdout; returns 1 on unsupported architecture
_koyeb_detect_arch() {
case "$(uname -m)" in
x86_64|amd64) arch="amd64" ;;
arm64|aarch64) arch="arm64" ;;
x86_64|amd64) echo "amd64" ;;
arm64|aarch64) echo "arm64" ;;
*)
log_error "Unsupported architecture: $(uname -m)"
return 1
;;
esac
}
# Download and install the Koyeb CLI binary
# Usage: _koyeb_install_cli OS ARCH
_koyeb_install_cli() {
local os="$1" arch="$2"
local install_dir="$HOME/.koyeb/bin"
mkdir -p "$install_dir"
@ -72,6 +71,22 @@ ensure_koyeb_cli() {
log_error "Koyeb CLI not found in PATH after installation"
return 1
fi
}
# Ensure Koyeb CLI is installed
ensure_koyeb_cli() {
if command -v koyeb &>/dev/null; then
log_info "Koyeb CLI available"
return 0
fi
log_step "Installing Koyeb CLI..."
local os arch
os=$(_koyeb_detect_os) || return 1
arch=$(_koyeb_detect_arch) || return 1
_koyeb_install_cli "$os" "$arch" || return 1
log_info "Koyeb CLI installed"
}

View file

@ -134,26 +134,12 @@ _wait_for_webdock_server() {
WEBDOCK_SERVER_IP "Server" "${max_attempts}"
}
create_server() {
local name="$1"
local slug="${name}"
local location_id="${WEBDOCK_LOCATION:-fi}"
local profile_slug="${WEBDOCK_PROFILE:-webdockmicro}"
local image_slug="${WEBDOCK_IMAGE:-ubuntu2404}"
# Validate env var inputs to prevent injection into Python code
validate_resource_name "$location_id" || { log_error "Invalid WEBDOCK_LOCATION"; return 1; }
validate_resource_name "$profile_slug" || { log_error "Invalid WEBDOCK_PROFILE"; return 1; }
validate_resource_name "$image_slug" || { log_error "Invalid WEBDOCK_IMAGE"; return 1; }
validate_resource_name "$slug" || { log_error "Invalid server slug"; return 1; }
log_step "Creating Webdock server '$name' (profile: $profile_slug, location: $location_id)..."
# Get all SSH public key IDs
local public_keys_response
public_keys_response=$(webdock_api GET "/account/publicKeys")
local public_key_ids
public_key_ids=$(echo "$public_keys_response" | python3 -c "
# Fetch all SSH public key IDs from the Webdock account
# Returns: JSON array of key IDs (e.g., [1, 2, 3]) or "[]" if none
_webdock_get_public_key_ids() {
local response
response=$(webdock_api GET "/account/publicKeys")
echo "$response" | python3 -c "
import json, sys
data = json.loads(sys.stdin.read())
if isinstance(data, list):
@ -161,7 +147,53 @@ if isinstance(data, list):
else:
ids = []
print(json.dumps(ids))
" 2>/dev/null || echo "[]")
" 2>/dev/null || echo "[]"
}
# Validate Webdock server creation inputs
# Usage: _webdock_validate_inputs LOCATION PROFILE IMAGE SLUG
_webdock_validate_inputs() {
validate_resource_name "$1" || { log_error "Invalid WEBDOCK_LOCATION"; return 1; }
validate_resource_name "$2" || { log_error "Invalid WEBDOCK_PROFILE"; return 1; }
validate_resource_name "$3" || { log_error "Invalid WEBDOCK_IMAGE"; return 1; }
validate_resource_name "$4" || { log_error "Invalid server slug"; return 1; }
}
# Extract server slug from creation response or report failure
# Sets: WEBDOCK_SERVER_SLUG on success
# Usage: _webdock_handle_create_response RESPONSE
_webdock_handle_create_response() {
local response="$1"
if echo "$response" | grep -q '"slug"'; then
WEBDOCK_SERVER_SLUG=$(_extract_json_field "$response" "d['slug']")
export WEBDOCK_SERVER_SLUG
log_info "Server created: slug=$WEBDOCK_SERVER_SLUG"
return 0
fi
log_error "Failed to create Webdock server"
log_error "API Error: $(extract_api_error_message "$response" "$response")"
log_warn "Common issues:"
log_warn " - Insufficient account balance"
log_warn " - Profile/location unavailable (try different WEBDOCK_PROFILE or WEBDOCK_LOCATION)"
log_warn " - Server limit reached"
log_warn " - Slug already in use"
log_warn "Check your dashboard: https://my.webdock.io/"
return 1
}
create_server() {
local name="$1"
local slug="${name}"
local location_id="${WEBDOCK_LOCATION:-fi}"
local profile_slug="${WEBDOCK_PROFILE:-webdockmicro}"
local image_slug="${WEBDOCK_IMAGE:-ubuntu2404}"
_webdock_validate_inputs "$location_id" "$profile_slug" "$image_slug" "$slug" || return 1
log_step "Creating Webdock server '$name' (profile: $profile_slug, location: $location_id)..."
local public_key_ids
public_key_ids=$(_webdock_get_public_key_ids)
local body
body=$(_webdock_build_server_body "$name" "$slug" "$location_id" "$profile_slug" "$image_slug" "$public_key_ids")
@ -169,21 +201,7 @@ print(json.dumps(ids))
local response
response=$(webdock_api POST "/servers" "$body")
if echo "$response" | grep -q '"slug"'; then
WEBDOCK_SERVER_SLUG=$(echo "$response" | python3 -c "import json,sys; print(json.loads(sys.stdin.read())['slug'])")
export WEBDOCK_SERVER_SLUG
log_info "Server created: slug=$WEBDOCK_SERVER_SLUG"
else
log_error "Failed to create Webdock server"
log_error "API Error: $(extract_api_error_message "$response" "$response")"
log_warn "Common issues:"
log_warn " - Insufficient account balance"
log_warn " - Profile/location unavailable (try different WEBDOCK_PROFILE or WEBDOCK_LOCATION)"
log_warn " - Server limit reached"
log_warn " - Slug already in use"
log_warn "Check your dashboard: https://my.webdock.io/"
return 1
fi
_webdock_handle_create_response "$response" || return 1
_wait_for_webdock_server "$WEBDOCK_SERVER_SLUG"
}