Skip to content
This repository was archived by the owner on Aug 16, 2021. It is now read-only.

Commit 11723f0

Browse files
authored
Merge branch 'master' into dmius-region-param
2 parents 021a722 + 5965a91 commit 11723f0

File tree

2 files changed

+169
-4
lines changed

2 files changed

+169
-4
lines changed

nancy_run.sh

Lines changed: 150 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ KEEP_ALIVE=0
1616
VERBOSE_OUTPUT_REDIRECT=" > /dev/null"
1717
EBS_SIZE_MULTIPLIER=15
1818
POSTGRES_VERSION_DEFAULT=10
19+
AWS_BLOCK_DURATION=0 # by default no time limit
1920

2021
#######################################
2122
# Print an error/warning/notice message to STDERR
@@ -502,6 +503,9 @@ while [ $# -gt 0 ]; do
502503
AWS_EBS_VOLUME_SIZE="$2"; shift 2 ;;
503504
--aws-region )
504505
AWS_REGION="$2"; shift 2 ;;
506+
--aws-block-duration )
507+
AWS_BLOCK_DURATION=$2; shift 2 ;;
508+
505509
--s3cfg-path )
506510
S3_CFG_PATH="$2"; shift 2 ;;
507511
* )
@@ -549,6 +553,45 @@ if $DEBUG ; then
549553
echo "AWS_EBS_VOLUME_SIZE: $AWS_EBS_VOLUME_SIZE"
550554
fi
551555

556+
#######################################
557+
# Check path to file/directory.
558+
# Globals:
559+
# None
560+
# Arguments:
561+
# (text) name of the variable holding the
562+
# file path (starts with 'file://' or 's3://') or any string
563+
# Returns:
564+
# (integer) for input starting with 's3://' always returns 0
565+
# for 'file://': 0 if file exists locally, error if it doesn't
566+
# 1 if the input is empty,
567+
# -1 otherwise.
568+
#######################################
569+
function checkPath() {
570+
if [[ -z $1 ]]; then
571+
return 1
572+
fi
573+
eval path=\$$1
574+
575+
if [[ $path =~ "s3://" ]]; then
576+
dbg "$1 looks like a S3 file path. Warning: Its presence will not be checked!"
577+
return 0 # we do not actually check S3 paths at the moment
578+
elif [[ $path =~ "file://" ]]; then
579+
dbg "$1 looks like a local file path."
580+
path=${path/file:\/\//}
581+
if [[ -f $path ]]; then
582+
dbg "$path found."
583+
eval "$1=\"$path\"" # update original variable
584+
return 0 # file found
585+
else
586+
err "File '$path' is not found locally."
587+
exit 1
588+
fi
589+
else
590+
dbg "Value of $1 is not a file path. Use its value as a content."
591+
return -1 #
592+
fi
593+
}
594+
552595
### CLI parameters checks ###
553596
if [[ "$RUN_ON" == "aws" ]]; then
554597
if [ ! -z ${CONTAINER_ID+x} ]; then
@@ -569,6 +612,19 @@ if [[ "$RUN_ON" == "aws" ]]; then
569612
err "NOTICE: AWS EC2 region not given. Will used us-east-1."
570613
AWS_REGION='us-east-1'
571614
fi
615+
if [[ -z ${AWS_BLOCK_DURATION+x} ]]; then
616+
err "NOTICE: Container live time duration is not given."
617+
else
618+
case $AWS_BLOCK_DURATION in
619+
0|60|120|240|300|360)
620+
dbg "Container live time duration is $AWS_BLOCK_DURATION. "
621+
;;
622+
*)
623+
err "Container live time duration (--aws-block-duration) has wrong value: $AWS_BLOCK_DURATION. Available values of AWS spot instance duration in minutes is 60, 120, 180, 240, 300, or 360)."
624+
exit 1
625+
;;
626+
esac
627+
fi
572628
elif [[ "$RUN_ON" == "localhost" ]]; then
573629
if [[ ! -z ${AWS_KEYPAIR_NAME+x} ]] || [[ ! -z ${AWS_SSH_KEY_PATH+x} ]] ; then
574630
err "ERROR: options '--aws-keypair-name' and '--aws-ssh-key-path' must be used with '--run-on aws'."
@@ -586,6 +642,10 @@ elif [[ "$RUN_ON" == "localhost" ]]; then
586642
err "ERROR: option '--aws-region' must be used with '--run-on aws'."
587643
exit 1
588644
fi
645+
if [[ "$AWS_BLOCK_DURATION" != "0" ]]; then
646+
err "ERROR: option '--aws-block-duration' must be used with '--run on aws'."
647+
exit 1
648+
fi
589649
else
590650
err "ERROR: incorrect value for option --run-on"
591651
exit 1
@@ -799,7 +859,93 @@ else
799859
fi
800860
shopt -s expand_aliases
801861

802-
trap cleanup_and_exit EXIT
862+
## Docker tools
863+
function waitEC2Ready() {
864+
cmd=$1
865+
machine=$2
866+
checkPrice=$3
867+
while true; do
868+
sleep 5; STOP=1
869+
ps ax | grep "$cmd" | grep "$machine" >/dev/null && STOP=0
870+
((STOP==1)) && return 0
871+
if [ $checkPrice -eq 1 ]; then
872+
status=$( \
873+
aws ec2 describe-spot-instance-requests \
874+
--filters="Name=launch.instance-type,Values=$AWS_EC2_TYPE" \
875+
| jq '.SpotInstanceRequests | sort_by(.CreateTime) | .[] | .Status.Code' \
876+
| tail -n 1
877+
)
878+
if [[ "$status" == "\"price-too-low\"" ]]; then
879+
echo "price-too-low"; # this value is result of function (not message for user), will check later
880+
return 0
881+
fi
882+
fi
883+
done
884+
}
885+
886+
# Params:
887+
# 1) machine name
888+
# 2) AWS EC2 instance type
889+
# 3) price
890+
# 4) duration (minutes)
891+
# 5) key pair name
892+
# 6) key path
893+
# 7) zone
894+
function createDockerMachine() {
895+
msg "Attempt to create a docker machine..."
896+
docker-machine create --driver=amazonec2 \
897+
--amazonec2-request-spot-instance \
898+
--amazonec2-keypair-name="$5" \
899+
--amazonec2-ssh-keypath="$6" \
900+
--amazonec2-instance-type=$2 \
901+
--amazonec2-spot-price=$3 \
902+
--amazonec2-block-duration-minutes=$4 \
903+
--amazonec2-zone=$7 \
904+
$1 2> >(grep -v "failed waiting for successful resource state" >&2) &
905+
}
906+
907+
function destroyDockerMachine() {
908+
# If spot request wasn't fulfilled, there is no associated instance,
909+
# so "docker-machine rm" will show an error, which is safe to ignore.
910+
# We better filter it out to avoid any confusions.
911+
# What is used here is called "process substitution",
912+
# see https://www.gnu.org/software/bash/manual/bash.html#Process-Substitution
913+
# The same trick is used in createDockerMachine to filter out errors
914+
# when we have "price-too-low" attempts, such errors come in few minutes
915+
# after an attempt and are generally unexpected by user.
916+
cmdout=$(docker-machine rm --force $1 2> >(grep -v "unknown instance" >&2) )
917+
msg "Termination requested for machine, current status: $cmdout"
918+
}
919+
920+
function cleanupAndExit {
921+
if [ "$KEEP_ALIVE" -gt "0" ]; then
922+
msg "Debug timeout is $KEEP_ALIVE seconds – started."
923+
msg " To connect to the docker machine use:"
924+
msg " docker \`docker-machine config $DOCKER_MACHINE\` exec -it pg_nancy_${CURRENT_TS} bash"
925+
sleep $KEEP_ALIVE
926+
fi
927+
msg "Remove temp files..." # if exists
928+
if [[ ! -z "${dockerConfig+x}" ]]; then
929+
docker $dockerConfig exec -i ${containerHash} bash -c "sudo rm -rf $MACHINE_HOME"
930+
fi
931+
rm -rf "$TMP_PATH"
932+
if [[ "$RUN_ON" == "localhost" ]]; then
933+
msg "Remove docker container"
934+
docker container rm -f $containerHash
935+
elif [[ "$RUN_ON" == "aws" ]]; then
936+
destroyDockerMachine $DOCKER_MACHINE
937+
if [ ! -z ${VOLUME_ID+x} ]; then
938+
msg "Wait and delete volume $VOLUME_ID"
939+
sleep 60 # wait for the machine to be removed
940+
delvolout=$(aws ec2 delete-volume --volume-id $VOLUME_ID)
941+
msg "Volume $VOLUME_ID deleted"
942+
fi
943+
else
944+
err "ASSERT: must not reach this point"
945+
exit 1
946+
fi
947+
}
948+
trap cleanupAndExit EXIT
803949

804950
if [[ "$RUN_ON" == "localhost" ]]; then
805951
if [[ -z ${CONTAINER_ID+x} ]]; then
@@ -838,7 +984,7 @@ elif [[ "$RUN_ON" == "aws" ]]; then
838984
fi
839985

840986
create_ec2_docker_machine $DOCKER_MACHINE $AWS_EC2_TYPE $EC2_PRICE \
841-
60 $AWS_KEYPAIR_NAME $AWS_SSH_KEY_PATH $AWS_REGION $AWS_ZONE;
987+
$AWS_BLOCK_DURATION $AWS_KEYPAIR_NAME $AWS_SSH_KEY_PATH $AWS_REGION $AWS_ZONE;
842988
status=$(wait_ec2_docker_machine_ready "$DOCKER_MACHINE" true)
843989
if [[ "$status" == "price-too-low" ]]; then
844990
msg "Price $price is too low for $AWS_EC2_TYPE instance. Getting the up-to-date value from the error message..."
@@ -866,10 +1012,10 @@ elif [[ "$RUN_ON" == "aws" ]]; then
8661012
DOCKER_MACHINE="${DOCKER_MACHINE//_/-}"
8671013
#try start docker machine name with new price
8681014
create_ec2_docker_machine $DOCKER_MACHINE $AWS_EC2_TYPE $EC2_PRICE \
869-
60 $AWS_KEYPAIR_NAME $AWS_SSH_KEY_PATH $AWS_REGION $AWS_ZONE
1015+
$AWS_BLOCK_DURATION $AWS_KEYPAIR_NAME $AWS_SSH_KEY_PATH $AWS_REGION $AWS_ZONE
8701016
wait_ec2_docker_machine_ready "$DOCKER_MACHINE" false;
8711017
else
872-
err "$(date "+%Y-%m-%d %H:%M:%S") ERROR: Cannot determine actual price for the instance $AWS_EC2_TYPE."
1018+
err "ERROR: Cannot determine actual price for the instance $AWS_EC2_TYPE."
8731019
exit 1;
8741020
fi
8751021
fi
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/bin/bash
2+
3+
output=$(
4+
${BASH_SOURCE%/*}/../nancy run \
5+
--run-on aws \
6+
--aws-keypair-name awskey \
7+
--aws-ssh-key-path /path/.ssh/awskey.pem \
8+
--aws-ec2-type i3.large \
9+
--aws-block-duration 30 \
10+
2>&1
11+
)
12+
13+
if [[ $output =~ " Container live time duration (--aws-block-duration) has wrong value: 30. Available values of AWS spot instance duration in minutes is 60, 120, 180, 240, 300, or 360)." ]]; then
14+
echo -e "\e[36mOK\e[39m"
15+
else
16+
>&2 echo -e "\e[31mFAILED\e[39m"
17+
>&2 echo -e "Output: $output"
18+
exit 1
19+
fi

0 commit comments

Comments
 (0)