Christine Lindauer
Christine Lindauer

Reputation: 93

How to wait in bash script until AWS instance creation is complete

I'm using a bash script to create an AWS instance via CLI and a cloudformation template. I want my script to wait until the instance creation is complete before I move on in my script. Right now, I'm using a while loop to "describe-stacks" every 5 seconds, and breaking out of the loop when the status = "CREATE_COMPLETE" or some failure status. Does anyone know of a more elegant way to do this?

stackStatus="CREATE_IN_PROGRESS"

while [[ 1 ]]; do
    echo "${AWS_CLI_PATH}" cloudformation describe-stacks --region "${CfnStackRegion}" --stack-name "${CfnStackName}"
    response=$("${AWS_CLI_PATH}" cloudformation describe-stacks --region "${CfnStackRegion}" --stack-name "${CfnStackName}" 2>&1)
    responseOrig="$response"
    response=$(echo "$response" | tr '\n' ' ' | tr -s " " | sed -e 's/^ *//' -e 's/ *$//')

    if [[ "$response" != *"StackStatus"* ]]
    then
        echo "Error occurred creating AWS CloudFormation stack. Error:"
        echo "    $responseOrig"
        exit -1
    fi

    stackStatus=$(echo $response | sed -e 's/^.*"StackStatus"[ ]*:[ ]*"//' -e 's/".*//')
    echo "    StackStatus: $stackStatus"

    if [[ "$stackStatus" == "ROLLBACK_IN_PROGRESS" ]] || [[ "$stackStatus" == "ROLLBACK_COMPLETE" ]] || [[ "$stackStatus" == "DELETE_IN_PROGRESS" ]] || [[ "$stackStatus" == "DELETE_COMPLETE" ]]; then
        echo "Error occurred creating AWS CloudFormation stack and returned status code ROLLBACK_IN_PROGRESS. Details:"
        echo "$responseOrig"
        exit -1
    elif [[ "$stackStatus" == "CREATE_COMPLETE" ]]; then
        break
    fi

    # Sleep for 5 seconds, if stack creation in progress
    sleep 5
done

Upvotes: 9

Views: 11156

Answers (4)

Zvika
Zvika

Reputation: 83

The below is a general "check_status" function. Useful for multiple action such as checking whether stack has been deployed or an EKS cluster is up and whether nodes were added to it.

check_status() {

    max_tries="$1"
    test_command="$2"
    required_value="$3"
    error="$4"

    ok="false"
    for i in `seq 1 $max_tries`; do
        return_value=$(eval ${test_command})
        if [ "$return_value" == "$required_value" ]; then
            ok="true"
            break
        else
            echo -n "."
        fi
        sleep 5
    done
    if [ "$ok" == "false" ]; then
        printf "\n\e[31mERROR:\e[0m $error\n"
        exit 1
    fi 
}

check_vpc() {
    echo "Waiting for stack status..."
    vpc_stack_status="aws cloudformation describe-stacks --stack- 
    name=${vpc_stack_name} --query 'Stacks[0].StackStatus' --output text"
    msg="Stack creation failed - giving up"
    check_status "100" "$vpc_stack_status" "CREATE_COMPLETE" "$msg"
    [[ $? == "0" ]] && echo "VPC stack deployed successfully"
}

Upvotes: 1

Patrick Crocker
Patrick Crocker

Reputation: 203

The aws cli provides a wait subcommand for most of the commands that create resources. For your scenario, you can use the wait subcommand to wait for the stack-create-complete event:

aws cloudformation wait stack-create-complete --stack-name myStackName

Upvotes: 10

LPby
LPby

Reputation: 529

That is how I did it. After start of instance I wait for public IP:

INSTANCE_ID="$(aws ec2 run-instances --cli-input-json "${LAUNCH_SPEC}" | jq -r '.Instances[0].InstanceId')"
echo "Instance id ${INSTANCE_ID}"

while true; do
    PUBLIC_IP="$(aws ec2 describe-instances --instance-ids ${INSTANCE_ID} | jq -r '.Reservations[0].Instances[0].PublicIpAddress')"
    if [[ "${PUBLIC_IP}" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then break; fi
    sleep 1
    echo -n '.'
done

LAUNCH_SPEC defined previously

Upvotes: 5

Kevin S
Kevin S

Reputation: 511

Ec2-wait-instance-exists seems like what you need: http://docs.aws.amazon.com/cli/latest/reference/ec2/wait/instance-exists.html

Upvotes: 5

Related Questions