Search code examples
bashgoogle-cloud-platformsshgoogle-compute-enginegcloud

How to start a GCE instance before SSH connection?


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

Solution

  • 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.