diff --git a/src/aws/dependencies/utilitiyFunction.sh b/src/aws/dependencies/utilitiyFunction.sh index 2a00353..1b2d7aa 100644 --- a/src/aws/dependencies/utilitiyFunction.sh +++ b/src/aws/dependencies/utilitiyFunction.sh @@ -1,4 +1,3 @@ - # Filters instances from JSON data based on the tag "Class" with a value of "treehouses". # Expects JSON data in the format returned by the AWS CLI command 'describe-instances'. # Uses 'jq' to parse and filter the data. @@ -9,43 +8,90 @@ function filterInstancesByTag { echo "$jsonData" | jq '[.Reservations[].Instances[] | select(.Tags[]? | .Key=="Class" and .Value=="treehouses")]' } -function waitForOutput(){ - local cmd=$1 - local result=$(eval $cmd) - while [ -z "$result" ] || [ "$result" == "null" ] - do - sleep 5 - result=$(eval $cmd) - done - echo $result +function waitForOutput() { + local cmd=$1 + local result=$(eval $cmd) + while [ -z "$result" ] || [ "$result" == "null" ]; do + sleep 5 + result=$(eval $cmd) + done + echo $result } setBalloonName() { - if [ -z "$1" ]; then - echo "luftballon" - else - echo "$1" - fi + if [ -z "$1" ]; then + echo "luftballon" + else + echo "$1" + fi } function makePortArray { - local portString="$1" - local -a portArray + local portString="$1" + local -a portArray - IFS=',' read -ra pairs <<< "$portString" + IFS=',' read -ra pairs <<<"$portString" - for pair in "${pairs[@]}"; do - IFS=':' read -ra ports <<< "$pair" - for port in "${ports[@]}"; do - portArray+=("$port") - done + for pair in "${pairs[@]}"; do + IFS=':' read -ra ports <<<"$pair" + for port in "${ports[@]}"; do + portArray+=("$port") done + done + + echo "${portArray[@]}" +} - echo "${portArray[@]}" +function getState() { + local instanceId=$1 + local state=$(aws ec2 describe-instances --instance-ids $instanceId | jq '.Reservations[].Instances[].State.Name') + echo $state } -function getState(){ - local instanceId=$1 - local state=$(aws ec2 describe-instances --instance-ids $instanceId | jq '.Reservations[].Instances[].State.Name') - echo $state +# Function: waitForConditionalOutput +# Description: Waits for a command to produce a specific result based on the specified mode. +# Parameters: +# $1 - The command to execute +# $2 - The target value to compare against +# $3 - The mode of operation: 'match' or 'different' +# 'match': Waits for the result to match the target value +# 'different': Waits for the result to be different from the target value +# Returns: +# 0 - If the desired condition is met within the max attempts +# 1 - If the desired condition is not met within the max attempts + +function waitForConditionalOutput() { + local cmd=$1 + local targetValue=$2 + local mode=$3 + local maxAttempts=3 + local attempt=0 + + # Validate mode + if [[ "$mode" != "match" && "$mode" != "different" ]]; then + echo "Error: Invalid mode. Use 'match' or 'different'." + return 1 + fi + + while [ $attempt -lt $maxAttempts ]; do + local result=$(eval $cmd) + if [ "$mode" == "match" ]; then + # Wait for the result to match the target value + if [ "$result" == "$targetValue" ]; then + echo $result + return 0 + fi + elif [ "$mode" == "different" ]; then + # Wait for the result to be different from the target value + if [ "$result" != "$targetValue" ]; then + echo $result + return 0 + fi + fi + attempt=$((attempt + 1)) + sleep 10 + done + + echo "Error: Failed to meet the condition after $maxAttempts attempts." + return 1 } diff --git a/src/aws/start.sh b/src/aws/start.sh index 76cec03..0933a39 100644 --- a/src/aws/start.sh +++ b/src/aws/start.sh @@ -3,49 +3,48 @@ #BASE=$HOME BASE=/home/pi -function start(){ - balloonName=$(setBalloonName "$1") +function start() { + balloonName=$(setBalloonName "$1") - if ! isBalloonNameValid "$balloonName"; then - echo "Please provide a valid balloon name" - exit 1 - fi + if ! isBalloonNameValid "$balloonName"; then + echo "Please provide a valid balloon name" + exit 1 + fi - instanceId=$(getValueByAttribute $balloonName instanceId) + instanceId=$(getValueByAttribute "$balloonName" instanceId) - if [ "$instanceId" = "null" ]; then - echo "$balloonName does not exist" - exit 1 - fi + if [ "$instanceId" = "null" ]; then + echo "$balloonName does not exist" + exit 1 + fi - oldPublicIp=$(getValueByAttribute $balloonName publicIp) + # oldPublicIp=$(getValueByAttribute "$balloonName" publicIp) - state=$(getState $instanceId) + state=$(waitForConditionalOutput "getState $instanceId" "\"stopping\"" "different") + if [ $? -ne 0 ]; then + echo "Wait for starting on start command until instance is stopped." + exit 1 + fi - if [ "$state" == "\"running\"" ]; then - echo "The instance is already running" - exit 0 - fi + if [ "$state" == "\"running\"" ]; then + echo "The instance is already running" + exit 0 + fi - if [ "$state" == "\"stopping\"" ]; then - echo "The instance is stopping" - exit 1 - fi + aws ec2 start-instances --instance-ids "$instanceId" - aws ec2 start-instances --instance-ids $instanceId + echo "get the new ip address. The procedure might take time for a while" + publicIp=$(waitForOutput "getLatestIpAddress $instanceId") - echo "get the new ip address. The procedure might take time for a while" - publicIp=$(waitForOutput "getLatestIpAddress $instanceId") + # portConfigArray=$(getArrayValueAsStringByKey "$instanceName" tcpPortArray) - portConfigArray=$(getArrayValueAsStringByKey $instanceName tcpPortArray) + echo "the new ip address is $publicIp" + updateIPAddress "$balloonName" "$publicIp" - echo "the new ip address is $publicIp" - updateIPAddress $balloonName $publicIp + closeSSHTunnel + echo "remove old ssh tunnel settings" + sleep 5 - closeSSHTunnel - echo "remove old ssh tunnel settings" - sleep 5 - - restartSSHTunnel $balloonName $publicIp - echo "open new ssh tunnel" + restartSSHTunnel "$balloonName" "$publicIp" + echo "open new ssh tunnel" } diff --git a/src/aws/up.sh b/src/aws/up.sh index e31d8ec..5cc9664 100644 --- a/src/aws/up.sh +++ b/src/aws/up.sh @@ -158,7 +158,6 @@ function up { echo "Success to add ssh key: $importedKeyName" else echo "The key pair $keyname already exists. Please use another key name." - importedKeyName=$keyname fi if ! checkSecurityGroup; then @@ -169,44 +168,54 @@ function up { echo "Security Group already exists." fi - instanceId=$(checkInstance) - if [ -z "$instanceId" ]; then - instanceState="" + createAndTagInstance() { instanceId=$(createEc2 | getValueByKeyword InstanceId) echo "Creating and running EC2 instance..." echo "Instance id is $instanceId" + aws ec2 create-tags --resources $instanceId --tags Key=Name,Value=$instanceName aws ec2 create-tags --resources $instanceId --tags Key=Class,Value=treehouses + publicIp=$(waitForOutput "getLatestIpAddress $instanceId") echo "Public IP Address is $publicIp" echo "Will open ssh tunnel soon" + isOpen=$(waitForOutput "ssh-keyscan -H $publicIp | grep ecdsa-sha2-nistp256") echo "Opened ssh tunnel" + openSSHTunnel $instanceName $publicIp $portConfigArray - storeConfigIntoTreehousesConfigAsStringfiedJson $instanceName $importedKeyName $instanceId $publicIp $groupNameaws ec2 create-tags --resources $instanceId --tags Key=Class,Value=treehouses + storeConfigIntoTreehousesConfigAsStringfiedJson $instanceName $importedKeyName $instanceId $publicIp $groupName + } + + instanceId=$(checkInstance) + if [ -z "$instanceId" ]; then + createAndTagInstance + else + instanceState=$(waitForConditionalOutput "checkInstanceState $instanceId" "\"stopping\"" "different") + if [ $? -ne 0 ]; then + echo "Wait for starting on start command until instance is stopped." + exit 1 + fi + echo "Success to add ssh key: $importedKeyName" else - instanceState=$(checkInstanceState $instanceId) - if [ "$instanceState" = "running" ]; then + echo "The key pair $keyname already exists. Please use another key name." + importedKeyName=$keyname + fi + + case "$instanceState" in + "running") echo "EC2 instance is already running." - elif [ "$instanceState" = "stopped" ]; then + ;; + "stopped") echo "Starting stopped EC2 instance..." start $instanceName - elif [ "$instanceState" = "terminated" ]; then - instanceState="" - instanceId=$(createEc2 | getValueByKeyword InstanceId) - echo "Creating and running EC2 instance..." - echo "Instance id is $instanceId" - aws ec2 create-tags --resources $instanceId --tags Key=Name,Value=$instanceName - aws ec2 create-tags --resources $instanceId --tags Key=Class,Value=treehouses - publicIp=$(waitForOutput "getLatestIpAddress $instanceId") - echo "Public IP Address is $publicIp" - echo "Will open ssh tunnel soon" - isOpen=$(waitForOutput "ssh-keyscan -H $publicIp | grep ecdsa-sha2-nistp256") - echo "Opened ssh tunnel" - openSSHTunnel $instanceName $publicIp $portConfigArray - storeConfigIntoTreehousesConfigAsStringfiedJson $instanceName $importedKeyName $instanceId $publicIp $groupNameaws ec2 create-tags --resources $instanceId --tags Key=Class,Value=treehouses - else + ;; + "terminated") + createAndTagInstance + ;; + *) echo "EC2 instance is in state: $instanceState." - fi + ;; + esac fi }