9

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
2
  • 1
    Nothing wrong with this approach, just make sure you don't sit sleeping forever - you may want to break after a long time anyway. There are more elegant solutions, but probably beyond the scope of bash Commented Feb 17, 2015 at 14:36
  • 1
    I'd love to see a more elegant solution as well! (primarily to avoiding spamming aws api...) Commented Jun 30, 2015 at 7:21

4 Answers 4

10

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
Sign up to request clarification or add additional context in comments.

2 Comments

Although this code may help to solve the problem, it doesn't explain why and/or how it answers the question. Providing this additional context would significantly improve its long-term educational value. Please edit your answer to add explanation, including what limitations and assumptions apply.
This seems to be the correct way, but I'm getting a Waiter StackCreateComplete failed: Waiter encountered a terminal failure state
5

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

Comments

5

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

1 Comment

Adapted this for ECR to allow an EC2 instance to check if an image is available before it runs the container.
2

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"
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.