166 lines
5.5 KiB
YAML
166 lines
5.5 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
|
|
service-account-key:
|
|
description: "JSON representation of STACKIT service account key."
|
|
required: false
|
|
default: ""
|
|
service-account-key-path:
|
|
description: "Path to STACKIT service account key file."
|
|
required: false
|
|
default: ""
|
|
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 }}
|
|
INPUT_SERVICE_ACCOUNT_KEY: ${{ inputs.service-account-key }}
|
|
INPUT_SERVICE_ACCOUNT_KEY_PATH: ${{ inputs.service-account-key-path }}
|
|
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
|
|
|
|
if [ -z "$INPUT_SERVICE_ACCOUNT_KEY" ] && [ -z "$INPUT_SERVICE_ACCOUNT_KEY_PATH" ]; then
|
|
echo "::error:: You must provide either 'service-account-key' or 'service-account-key-path'."
|
|
exit 1
|
|
fi
|
|
|
|
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
|
|
|
|
echo "::group::Authenticating with service account and triggering operation"
|
|
|
|
if [ -n "$INPUT_SERVICE_ACCOUNT_KEY_PATH" ]; then
|
|
STACKIT_SERVICE_ACCOUNT_KEY_PATH="$INPUT_SERVICE_ACCOUNT_KEY_PATH"
|
|
else
|
|
STACKIT_SERVICE_ACCOUNT_KEY_PATH="$(mktemp)"
|
|
|
|
echo "Writing STACKIT service account key to $STACKIT_SERVICE_ACCOUNT_KEY_PATH"
|
|
echo "$INPUT_SERVICE_ACCOUNT_KEY" > "$STACKIT_SERVICE_ACCOUNT_KEY_PATH"
|
|
fi
|
|
|
|
export STACKIT_SERVICE_ACCOUNT_KEY_PATH
|
|
|
|
STACKIT_ACCESS_TOKEN="$(stackit auth activate-service-account --only-print-access-token)"
|
|
export STACKIT_ACCESS_TOKEN
|
|
|
|
STACKIT_PROJECT_ID="$INPUT_PROJECT_ID"
|
|
export STACKIT_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::"
|
|
|
|
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
|
|
|
|
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
|