ske-operations/action.yml
Maximilian Jugl 51475a9d48
All checks were successful
Check PR title / check (pull_request) Successful in 37s
feat: add state-match output
2026-05-15 12:09:00 +02:00

173 lines
5.7 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"
outputs:
state-match:
description: "A boolean value to indicate that the target state was already reached"
value: ${{ steps.trigger-op.outputs.state-match }}
runs:
using: composite
steps:
- name: Trigger SKE operation
id: trigger-op
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"
if [ -n "$INPUT_SERVICE_ACCOUNT_KEY_PATH" ]; then
STACKIT_SERVICE_ACCOUNT_KEY_PATH="$INPUT_SERVICE_ACCOUNT_KEY_PATH"
export STACKIT_SERVICE_ACCOUNT_KEY_PATH
else
STACKIT_SERVICE_ACCOUNT_KEY_PATH="$(mktemp)"
export STACKIT_SERVICE_ACCOUNT_KEY_PATH
echo "Writing STACKIT service account key to $STACKIT_SERVICE_ACCOUNT_KEY_PATH"
printf "%s\n" "$INPUT_SERVICE_ACCOUNT_KEY" > "$STACKIT_SERVICE_ACCOUNT_KEY_PATH"
fi
stackit auth activate-service-account
STACKIT_PROJECT_ID="$INPUT_PROJECT_ID"
export STACKIT_PROJECT_ID
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."
echo "state-match=true" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "Unexpected cluster status: $CURRENT_STATUS."
exit 1
fi
echo "state-match=false" >> "$GITHUB_OUTPUT"
stackit curl --fail -X POST "https://ske.api.stackit.cloud/v2/projects/$INPUT_PROJECT_ID/regions/$INPUT_REGION/clusters/$INPUT_CLUSTER_NAME/$ENDPOINT"
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