ske-operations/action.yml

138 lines
4.4 KiB
YAML

name: "Trigger SKE operations"
description: "Performs operations on SKE clusters (wake, hibernate, reconcile, maintenance)."
inputs:
action:
description: "Operation to perform."
required: true
region:
description: "Data center region of SKE cluster."
required: true
project-id:
description: "STACKIT project ID."
required: true
cluster-name:
description: "Name of SKE cluster."
required: true
timeout-seconds:
description: "Time in seconds after which target state check fails."
required: false
default: "900"
interval-seconds:
description: "Time in seconds between target state checks."
required: false
default: "5"
wait:
description: "Wait until target state of operation has been reached."
required: false
default: "true"
runs:
using: composite
steps:
- name: Trigger SKE operation
shell: sh
env:
INPUT_ACTION: ${{ inputs.action }}
INPUT_REGION: ${{ inputs.region }}
INPUT_PROJECT_ID: ${{ inputs.project-id }}
INPUT_CLUSTER_NAME: ${{ inputs.cluster-name }}
INPUT_TIMEOUT_SECS: ${{ inputs.timeout-seconds }}
INPUT_INTERVAL_SECS: ${{ inputs.interval-seconds }}
INPUT_WAIT: ${{ inputs.wait }}
run: |
set -e
for cmd in stackit jq grep; do
if ! command -v "$cmd" > /dev/null 2>&1; then
echo "'$cmd' not installed."
exit 1
fi
done
URL_SAFE_REGEX="^[a-zA-Z0-9._~-]+$"
for input in "$INPUT_ACTION" "$INPUT_REGION" "$INPUT_PROJECT_ID" "$INPUT_CLUSTER_NAME"; do
if ! printf "%s\n" "$input" | grep -Eq "$URL_SAFE_REGEX"; then
echo "'$input' is not a URL-safe input."
exit 1
fi
done
TIMEOUT_SECS="${INPUT_TIMEOUT_SECS:-900}"
INTERVAL_SECS="${INPUT_INTERVAL_SECS:-5}"
WAIT="${INPUT_WAIT:-true}"
case "$INPUT_ACTION" in
hibernate)
TARGET_STATUS="STATE_HIBERNATED"
INITIAL_STATUS="STATE_HEALTHY"
ENDPOINT="hibernate"
;;
wake)
TARGET_STATUS="STATE_HEALTHY"
INITIAL_STATUS="STATE_HIBERNATED"
ENDPOINT="wakeup"
;;
reconcile)
TARGET_STATUS="STATE_HEALTHY"
INITIAL_STATUS="STATE_HEALTHY"
ENDPOINT="reconcile"
;;
maintenance)
TARGET_STATUS="STATE_HEALTHY"
INITIAL_STATUS="STATE_HEALTHY"
ENDPOINT="maintenance"
;;
*)
echo "Unexpected action '$INPUT_ACTION'. Must be one of: wake, hibernate, reconcile, maintenance."
exit 1
;;
esac
CURRENT_STATUS="$(stackit ske cluster describe "$INPUT_CLUSTER_NAME" -ojson | jq -r '.status.aggregated')"
if [ "$CURRENT_STATUS" != "$INITIAL_STATUS" ]; then
if [ "$CURRENT_STATUS" = "$TARGET_STATUS" ]; then
echo "Cluster is already in desired state."
exit 0
fi
echo "Unexpected cluster status: $CURRENT_STATUS."
exit 1
fi
echo "::group::Authenticating with service account and triggering operation"
STACKIT_ACCESS_TOKEN="$(stackit auth activate-service-account --only-print-access-token)"
export STACKIT_ACCESS_TOKEN
stackit config set --project-id "$INPUT_PROJECT_ID"
stackit curl --fail -X POST "https://ske.api.stackit.cloud/v2/projects/$INPUT_PROJECT_ID/regions/$INPUT_REGION/clusters/$INPUT_CLUSTER_NAME/$ENDPOINT"
echo "::endgroup::"
if [ "$WAIT" != "true" ]; then
echo "Operation triggered. No wait requested, exiting."
exit 0
fi
START_TIME="$(date +%s)"
SECS_ELAPSED=0
while [ "$SECS_ELAPSED" -lt "$TIMEOUT_SECS" ]; do
CURRENT_STATUS="$(stackit ske cluster describe "$INPUT_CLUSTER_NAME" -ojson | jq -r '.status.aggregated')"
if [ "$CURRENT_STATUS" = "$TARGET_STATUS" ]; then
echo "Targeted state reached after $SECS_ELAPSED seconds, exiting."
exit 0
fi
echo "Target state not reached, waiting ${INTERVAL_SECS}s... (elapsed: ${SECS_ELAPSED}s)"
sleep "$INTERVAL_SECS"
CURRENT_TIME="$(date +%s)"
SECS_ELAPSED=$((CURRENT_TIME - START_TIME))
done
echo "::error::Target state not reached after $SECS_ELAPSED seconds, exiting."
exit 1