2

I'm trying to check the status of AWS AMI and execute some commands if the status is available. Below is my small script to achieve that.

#!/usr/bin/env bash

REGION="us-east-1"
US_EAST_AMI="ami-0130c3a072f3832ff"

while :
do
      AMI_STATE=$(aws ec2 describe-images --region "$REGION" --image-ids $US_EAST_AMI | jq -r .Images[].State)

        [ "$AMI_STATE" == "available" ] && echo "Now the AMI is available in the $REGION region" && break
        sleep 10
done

The above script works fine if the first call was a success. But I'm expecting something for the below scenarios

  • If the value of the $AMI_STATE is equal to "available"(currently working), "failed" it should break the loop
  • If the value of the $AMI_STATE is equal to "pending", the loop should continue until it meets the expected value.
2
  • So, um, add another test to see if the variable contains failed ?
    – ilkkachu
    Aug 17 at 14:36
  • 1
    Note how the answer you received is using lower case variables: this is good practice. You should avoid using CAPS for variable names in shell scripts since, by convention, global environment variables are capitalized and using caps for your own variables can lead to hard to debug bugs caused by naming collisions.
    – terdon
    Aug 17 at 14:48

2 Answers 2

7

You want to run the loop while the value of AMI_STATE is equal to pending… so write just that.

while
    AMI_STATE=$(aws ec2 describe-images --region "$REGION" --image-ids $US_EAST_AMI | jq -r .Images[].State) &&
    [ "$AMI_STATE" = "pending" ]
do
    sleep 10
done
case $AMI_STATE in
    "") echo "Something went wrong: unable to retrieve AMI state";;
    available) echo "Now the AMI is available in the $REGION region";;
    failed) echo "The AMI has failed";;
    *) echo "AMI in weird state: $AMI_STATE";;
esac
1
  • Note that the comparison with the string pending could be done in jq and the exit status from jq could be made to reflect the outcome of that test if you use the utility with its -e option.
    – Kusalananda
    Aug 19 at 18:24
5

You could use a simple if construct:

#!/usr/bin/env bash

region="us-east-1"
us_east_ami="ami-0130c3a072f3832ff"

while :
do
    ami_state=$(aws ec2 describe-images --region "$region" --image-ids "$us_east_ami" | jq -r .Images[].State)
    if [[ $ami_state == available ]]; then
        echo "Now the AMI is available in the $region region"
        break
    elif [[ $ami_state == failed ]]; then
        echo "AMI is failed in $region region"
        break
    fi
    sleep 10
done

case would also be a good option here:

#!/usr/bin/env bash

region="us-east-1"
us_east_ami="ami-0130c3a072f3832ff"

while :
do
    ami_state=$(aws ec2 describe-images --region "$region" --image-ids "$us_east_ami" | jq -r .Images[].State)

    case $ami_state in
        available)
            echo "Now the AMI is available in the $region region"
            break
        ;;
        failed)
            echo "AMI is failed in $region region"
            break
        ;;
        pending) echo "AMI is still pending in $region region";;
        *)
            echo "AMI is in unhandled state: $ami_state"
            break
        ;;
    esac
    sleep 10
done

You can read about both in the bash manual 3.2.5.2 Conditional Constructs

Alternatively you might consider scrapping the infinite while loop in favor of an until loop:

#!/usr/bin/env bash

region="us-east-1"
us_east_ami="ami-0130c3a072f3832ff"

until [[ $ami_state == available ]]; do
    if [[ $ami_state == failed ]]; then
        echo "AMI is in a failed state for $region region"
        break
    fi
    ami_state=$(aws ec2 describe-images --region "$region" --image-ids "$us_east_ami" | jq -r .Images[].State)
    sleep 10
done

This will loop as many times as needed until the state becomes available. Which could easily turn into an infinite loop without the proper error handling. (Make sure there are no states other than failed that could wedge things)

4
  • @StéphaneChazelas good point
    – jesse_b
    Aug 17 at 14:41
  • @jesse_b the loop should continue only if the state is pending. Does this work in your provided solution? Aug 17 at 14:57
  • 1
    @Ravichandran: That is how the case solution would work, the others can easily be modified to behave that way. If you run into any issues building your if construct that can't be answered by the bash manual I'm sure that would warrant another question.
    – jesse_b
    Aug 17 at 15:00
  • yep, this works as expected. After this script execution, I need to execute another command outside of this script, only if the state is available. I'm trying something like below echo "Now the AMI is available in the $REGION region" && echo $(export AMI_STATE="available") but unsuccessful Aug 17 at 16:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.