mirror of
https://github.com/OpenRouterTeam/spawn.git
synced 2026-05-19 08:01:17 +00:00
refactor: Deduplicate API retry logic in UpCloud and Scaleway wrappers (#89)
Add generic_cloud_api_custom_auth() to shared/common.sh for cloud providers that use non-Bearer auth headers. Replace ~120 lines of duplicated retry logic in upcloud_api() and scaleway_api() with calls to the new shared function. 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:
parent
531a817bfe
commit
66701d3cf9
3 changed files with 82 additions and 110 deletions
|
|
@ -30,66 +30,16 @@ readonly SCALEWAY_ACCOUNT_API="https://api.scaleway.com/account/v3"
|
|||
# Configurable timeout/delay constants
|
||||
INSTANCE_STATUS_POLL_DELAY=${INSTANCE_STATUS_POLL_DELAY:-5}
|
||||
|
||||
# Scaleway API wrapper (uses X-Auth-Token header instead of Bearer)
|
||||
# Scaleway API wrapper (uses X-Auth-Token header instead of Bearer) with retry logic
|
||||
# Takes a full URL (not base+endpoint) for flexibility across Scaleway API namespaces
|
||||
scaleway_api() {
|
||||
local method="$1"
|
||||
local url="$2"
|
||||
local body="${3:-}"
|
||||
local max_retries="${4:-3}"
|
||||
|
||||
local attempt=1
|
||||
local interval=2
|
||||
local max_interval=30
|
||||
|
||||
while [[ "${attempt}" -le "${max_retries}" ]]; do
|
||||
local args=(
|
||||
-s
|
||||
-w "\n%{http_code}"
|
||||
-X "${method}"
|
||||
-H "X-Auth-Token: ${SCW_SECRET_KEY}"
|
||||
-H "Content-Type: application/json"
|
||||
)
|
||||
|
||||
if [[ -n "${body}" ]]; then
|
||||
args+=(-d "${body}")
|
||||
fi
|
||||
|
||||
local response
|
||||
response=$(curl "${args[@]}" "${url}" 2>&1)
|
||||
local curl_exit_code=$?
|
||||
|
||||
local http_code
|
||||
http_code=$(echo "${response}" | tail -1)
|
||||
local response_body
|
||||
response_body=$(echo "${response}" | head -n -1)
|
||||
|
||||
if [[ ${curl_exit_code} -ne 0 ]]; then
|
||||
if ! _api_should_retry_on_error "${attempt}" "${max_retries}" "${interval}" "${max_interval}" "Scaleway API network error"; then
|
||||
log_error "Scaleway API network error after ${max_retries} attempts"
|
||||
return 1
|
||||
fi
|
||||
_update_retry_interval "interval" "max_interval"
|
||||
attempt=$((attempt + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
if [[ "${http_code}" == "429" ]] || [[ "${http_code}" == "503" ]]; then
|
||||
if ! _api_should_retry_on_error "${attempt}" "${max_retries}" "${interval}" "${max_interval}" "Scaleway API rate limited (HTTP ${http_code})"; then
|
||||
log_error "Scaleway API returned HTTP ${http_code} after ${max_retries} attempts"
|
||||
echo "${response_body}"
|
||||
return 1
|
||||
fi
|
||||
_update_retry_interval "interval" "max_interval"
|
||||
attempt=$((attempt + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "${response_body}"
|
||||
return 0
|
||||
done
|
||||
|
||||
log_error "Scaleway API retry logic exhausted"
|
||||
return 1
|
||||
# Pass empty base_url since url is already complete
|
||||
generic_cloud_api_custom_auth "" "$method" "$url" "$body" "$max_retries" \
|
||||
-H "X-Auth-Token: ${SCW_SECRET_KEY}"
|
||||
}
|
||||
|
||||
# Convenience wrapper for instance API
|
||||
|
|
|
|||
|
|
@ -1116,6 +1116,80 @@ generic_cloud_api() {
|
|||
return 1
|
||||
}
|
||||
|
||||
# Helper to make API request with custom curl auth args (e.g., Basic Auth, custom headers)
|
||||
# Returns: 0 on curl success, 1 on curl failure
|
||||
# Sets: API_HTTP_CODE and API_RESPONSE_BODY globals
|
||||
_make_api_request_custom_auth() {
|
||||
local url="${1}"
|
||||
local method="${2}"
|
||||
local body="${3:-}"
|
||||
shift 3
|
||||
# Remaining args are custom curl auth flags (e.g., -u "user:pass" or -H "X-Auth-Token: ...")
|
||||
|
||||
local args=(
|
||||
-s
|
||||
-w "\n%{http_code}"
|
||||
-X "${method}"
|
||||
-H "Content-Type: application/json"
|
||||
"$@"
|
||||
)
|
||||
|
||||
if [[ -n "${body}" ]]; then
|
||||
args+=(-d "${body}")
|
||||
fi
|
||||
|
||||
local response
|
||||
response=$(curl "${args[@]}" "${url}" 2>&1)
|
||||
local curl_exit_code=$?
|
||||
|
||||
_parse_api_response "${response}"
|
||||
|
||||
return ${curl_exit_code}
|
||||
}
|
||||
|
||||
# Generic cloud API wrapper with custom curl auth args
|
||||
# Like generic_cloud_api but accepts arbitrary curl flags for authentication
|
||||
# Usage: generic_cloud_api_custom_auth BASE_URL METHOD ENDPOINT BODY MAX_RETRIES AUTH_ARGS...
|
||||
# Example: generic_cloud_api_custom_auth "$API_BASE" GET "/account" "" 3 -H "X-Auth-Token: $TOKEN"
|
||||
# Example: generic_cloud_api_custom_auth "$API_BASE" POST "/servers" "$body" 3 -u "$USER:$PASS"
|
||||
generic_cloud_api_custom_auth() {
|
||||
local base_url="${1}"
|
||||
local method="${2}"
|
||||
local endpoint="${3}"
|
||||
local body="${4:-}"
|
||||
local max_retries="${5:-3}"
|
||||
shift 5
|
||||
# Remaining args are custom curl auth flags
|
||||
|
||||
local attempt=1
|
||||
local interval=2
|
||||
local max_interval=30
|
||||
|
||||
while [[ "${attempt}" -le "${max_retries}" ]]; do
|
||||
if ! _make_api_request_custom_auth "${base_url}${endpoint}" "${method}" "${body}" "$@"; then
|
||||
if ! _handle_api_transient_error "network" "${attempt}" "${max_retries}" "interval" "max_interval" ""; then
|
||||
return 1
|
||||
fi
|
||||
attempt=$((attempt + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
if [[ "${API_HTTP_CODE}" == "429" ]] || [[ "${API_HTTP_CODE}" == "503" ]]; then
|
||||
if ! _handle_api_transient_error "${API_HTTP_CODE}" "${attempt}" "${max_retries}" "interval" "max_interval" "${API_RESPONSE_BODY}"; then
|
||||
return 1
|
||||
fi
|
||||
attempt=$((attempt + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "${API_RESPONSE_BODY}"
|
||||
return 0
|
||||
done
|
||||
|
||||
log_error "Cloud API retry logic exhausted"
|
||||
return 1
|
||||
}
|
||||
|
||||
# ============================================================
|
||||
# Agent verification helpers
|
||||
# ============================================================
|
||||
|
|
|
|||
|
|
@ -23,67 +23,15 @@ readonly UPCLOUD_API_BASE="https://api.upcloud.com/1.3"
|
|||
# Configurable timeout/delay constants
|
||||
INSTANCE_STATUS_POLL_DELAY=${INSTANCE_STATUS_POLL_DELAY:-5}
|
||||
|
||||
# UpCloud API wrapper using Basic Auth
|
||||
# UpCloud API wrapper using Basic Auth with retry logic
|
||||
# Usage: upcloud_api METHOD ENDPOINT [BODY] [MAX_RETRIES]
|
||||
upcloud_api() {
|
||||
local method="$1"
|
||||
local endpoint="$2"
|
||||
local body="${3:-}"
|
||||
local max_retries="${4:-3}"
|
||||
|
||||
local attempt=1
|
||||
local interval=2
|
||||
local max_interval=30
|
||||
|
||||
while [[ "${attempt}" -le "${max_retries}" ]]; do
|
||||
local args=(
|
||||
-s
|
||||
-w "\n%{http_code}"
|
||||
-X "${method}"
|
||||
-u "${UPCLOUD_USERNAME}:${UPCLOUD_PASSWORD}"
|
||||
-H "Content-Type: application/json"
|
||||
)
|
||||
|
||||
if [[ -n "${body}" ]]; then
|
||||
args+=(-d "${body}")
|
||||
fi
|
||||
|
||||
local response
|
||||
response=$(curl "${args[@]}" "${UPCLOUD_API_BASE}${endpoint}" 2>&1)
|
||||
local curl_exit_code=$?
|
||||
|
||||
local http_code
|
||||
http_code=$(printf '%s' "${response}" | tail -1)
|
||||
local response_body
|
||||
response_body=$(printf '%s' "${response}" | head -n -1)
|
||||
|
||||
if [[ ${curl_exit_code} -ne 0 ]]; then
|
||||
if ! _api_should_retry_on_error "${attempt}" "${max_retries}" "${interval}" "${max_interval}" "UpCloud API network error"; then
|
||||
log_error "UpCloud API network error after ${max_retries} attempts: curl exit code ${curl_exit_code}"
|
||||
return 1
|
||||
fi
|
||||
_update_retry_interval "interval" "max_interval"
|
||||
attempt=$((attempt + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
if [[ "${http_code}" == "429" ]] || [[ "${http_code}" == "503" ]]; then
|
||||
if ! _api_should_retry_on_error "${attempt}" "${max_retries}" "${interval}" "${max_interval}" "UpCloud API returned HTTP ${http_code}"; then
|
||||
log_error "UpCloud API returned HTTP ${http_code} after ${max_retries} attempts"
|
||||
echo "${response_body}"
|
||||
return 1
|
||||
fi
|
||||
_update_retry_interval "interval" "max_interval"
|
||||
attempt=$((attempt + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "${response_body}"
|
||||
return 0
|
||||
done
|
||||
|
||||
log_error "UpCloud API retry logic exhausted"
|
||||
return 1
|
||||
generic_cloud_api_custom_auth "$UPCLOUD_API_BASE" "$method" "$endpoint" "$body" "$max_retries" \
|
||||
-u "${UPCLOUD_USERNAME}:${UPCLOUD_PASSWORD}"
|
||||
}
|
||||
|
||||
test_upcloud_credentials() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue