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