0

How to ensure that a GCE instance is RUNNING before connecting it?

Because this only works when the instance status is already RUNNING:

gcloud compute ssh --zone $ZONE --project $PROJECT $INSTANCE_NAME
Martin Zeitler
  • 1
  • 19
  • 155
  • 216

1 Answers1

3

There seem to be three different instance statuses: RUNNING, STOPPING and TERMINATED.
-- permits passing SSH parameters, alike -o ConnectTimeout=60 -o ConnectionAttempts=3.

#!/bin/bash
PROJECT=$1
ZONE=$2
INSTANCE_NAME=$3
SSH_DEBUG=false
IAP_TUNNEL=false
TROUBLESHOOT=false
TIMEOUT=60
ATTEMPTS=3

if [ $# != 3 ]; then
    echo "Usage: gcloud_ssh.sh PROJECT ZONE INSTANCE_NAME"
    exit 1
else
    declare -a PARAM
    PARAM=(--project "$PROJECT" --zone "$ZONE" "$INSTANCE_NAME")
fi

function getInstanceStatus() {
    gcloud compute instances describe "${PARAM[@]}" --format="get(status)"
}

function whileStopping() {
    echo "GCE instance \`$INSTANCE_NAME\` is shutting down."
    STATUS=$(getInstanceStatus)
}

function startInstance() {
    echo "GCE instance \`$INSTANCE_NAME\` will be brought up."
    gcloud compute instances start "${PARAM[@]}"
    STATUS=$(getInstanceStatus)
}

STATUS=$(getInstanceStatus)

# Loop while the instance status is `STOPPING`.
while [[ "$STATUS" = "STOPPING" ]]; do whileStopping; done

# Start instance, once the instance status is `TERMINATED`.
if [[ "$STATUS" = "TERMINATED" ]]; then startInstance; fi

# This `if` statement might never be the case.
if [[ "$STATUS" != "RUNNING" ]]; then exit 1; fi

# Open SSH, when the instance status is `RUNNING`.
if [[ $IAP_TUNNEL = true ]]; then PARAM=("${PARAM[@]}" --tunnel-through-iap); fi
if [[ $TROUBLESHOOT = true ]]; then PARAM=("${PARAM[@]}" --troubleshoot); fi
PARAM=("${PARAM[@]}" -- -o ConnectTimeout="$TIMEOUT" -o ConnectionAttempts="$ATTEMPTS")
if [[ $SSH_DEBUG = true ]]; then PARAM=("${PARAM[@]}" -v); fi
gcloud compute ssh "${PARAM[@]}"

Then one can define instances as alias shortcuts in file ~/.bash_aliases:

alias ssh_xyz='/home/scripts/gcloud_ssh.sh project-name zone-name instance-name'

This script needs role compute.instanceAdmin.v1 and has options SSH_DEBUG, IAP_TUNNEL, TROUBLESHOOT. And for shutting down the remote instance, that would be: sudo poweroff.

Martin Zeitler
  • 1
  • 19
  • 155
  • 216
  • Very interesting!!! Additional IAM permissions are required to check and start instances. Add those details to your answer. – John Hanley Jun 17 '22 at 17:53
  • Can one check permissions for the current user with `gcloud` and what would these be? – Martin Zeitler Jun 17 '22 at 18:32
  • User's do not have IAM roles, permissions are bound to projects and resources. The base command is `gcloud projects get-iam-policy`. You would need to write a script that processes the output from `gcloud projects get-iam-policy $GCP_PROJECT_NAME --flatten="bindings[].members" --format="table(bindings.members)"` – John Hanley Jun 17 '22 at 18:37
  • IIRC Daz Wilkins posted a good script on Stack Overflow. – John Hanley Jun 17 '22 at 18:39
  • I can filter for the current user and get the roles - but would need to know which roles. – Martin Zeitler Jun 17 '22 at 19:25
  • https://cloud.google.com/compute/docs/access/iam – John Hanley Jun 17 '22 at 19:37
  • To save you some time, I mean just add the required permissions to invoke those commands to your answer. – John Hanley Jun 17 '22 at 22:46
  • I can compare individual permissions, but listing permissions for predefined roles need different CLI arguments than custom roles. A solid permission check might be a whole script on it's own - and might need permission to Resource Management API. The issue was rather that the shell tried to execute output, which I've fixed by unwrapping the last `if` / `fi`. – Martin Zeitler Jun 19 '22 at 01:52
  • I did not mean that. Just mention which permissions are required to use your script. Not to modify your script to check permissions. – John Hanley Jun 19 '22 at 02:37