Skip to content

Instantly share code, notes, and snippets.

@jetztgradnet
Created February 3, 2011 02:43
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jetztgradnet/808948 to your computer and use it in GitHub Desktop.
Save jetztgradnet/808948 to your computer and use it in GitHub Desktop.
Script to start an Amazon ElasticBeanstalk application with configuration parameters
#!/bin/sh
########################################################
# history
########################################################
#
# 0.3 (2011-02-08)
# - create/update configuration template 'InitialConfig' instead
# of 'Default', which is not editable
#
# 0.2 (2011-02-03)
# - check whether SSH key exists
# - create/update configuration template 'Default'
# if not explicitly specified. Previously, the
# configuration template was named identically to
# the environment
#
# 0.1 (2011-02-03)
# - initial release
# "global" vars
APP=
ENV=
TMPL=
APPFILE=
APPDESCR=
ENVDESCR=
IMAGEID=
INSTANCETYPE=
VERSION=
OPTIONS=
KEYNAME=
OPTFILE=
CNAME=
CONTAINER=
DEFAULT_TEMPLATE_NAME="InitialConfig" # "Default" is not editable
TMPOPTFILE=`mktemp -p "$TMPDIR" launcfg.XXXXXXX`
# Beanstalk app parameters
MIN_COUNT=1
MAX_COUNT=1
SECGROUP=
PARAM1=
PARAM2=
PARAM3=
PARAM4=
PARAM5=
JDBC_CONNECTION_STRING=
ERROR=1
WARN=2
INFO=3
DEBUG=4
LOGLEVEL=$WARN
######################################################################
# some functions
SCRIPTNAME=$(basename $0)
function usage() {
echo >&2 "usage: $SCRIPTNAME <options> -a appname {-e envname|-T template}"
echo >&2 " $SCRIPTNAME <options> -a appname -e envname"
echo >&2 " create and start an application"
echo >&2 " $SCRIPTNAME <options> -a appname -T template"
echo >&2 " create an application and a configuration template"
echo >&2 ""
echo >&2 " -a appname application name (required)"
# "{-e envname|-T template} [-f appfile] [-k keyname] [-i image-id] [-t image-type] [-v version]"
echo >&2 " -e environment Name of environment to create"
echo >&2 " -T template Name of configuration template to create"
echo >&2 " -d desciption application description"
echo >&2 " -D desciption environment/template description"
echo >&2 ""
echo >&2 "* Instance parameters"
echo >&2 " -i image-id AMI id"
echo >&2 " -t instance-type Instance type, e.g. 'm1.small' or 't1.micro'"
echo >&2 " -C solution-stack solution stack to use"
echo >&2 " possible values:"
echo >&2 " '32' -> 32bit Amazon Linux running Tomcat 6"
echo >&2 " '64' -> 64bit Amazon Linux running Tomcat 6"
echo >&2 " or any other solution stack as shown by"
echo >&2 " elastic-beanstalk-list-available-solution-stacks"
echo >&2 " -c CNAME CNAME to be used for the environment"
echo >&2 " if empty, the environment is used"
echo >&2 ""
echo >&2 "* Security parameters"
echo >&2 " -k keyname name of SSH access key configured in EC2"
echo >&2 " -g security-group security group to apply"
echo >&2 " -o optionsfile file containing additional options in JSON format"
# application parameters
echo >&2 ""
echo >&2 "* Application parameters"
echo >&2 " -V version label for application version"
echo >&2 " -f location S3 location of application WAR file."
echo >&2 " Format: 'bucket/file_key'"
echo >&2 " If version is specified, but location is empty,"
echo >&2 " the AWS sample application is used"
echo >&2 " -1 value PARAM1"
echo >&2 " -2 value PARAM2"
echo >&2 " -3 value PARAM3"
echo >&2 " -4 value PARAM4"
echo >&2 " -5 value PARAM5"
echo >&2 " -j value JDBC_CONNECTION_STRING"
# min, max instance count
echo >&2 ""
echo >&2 "* Load-balancing parameters"
echo >&2 " -m max-count max number of instances to create"
echo >&2 " -M min-count min number of instances to create"
echo >&2 ""
echo >&2 "* Other parameters"
echo >&2 " -h usage show this help"
echo >&2 " -v increase verbosity"
echo >&2 " -q decrease verbosity"
}
function log() {
local level=$1
shift
if [ "$level" -le "$LOGLEVEL" ]; then
echo >&2 "== " "$@"
fi
}
function isLevel() {
local level=$1
shift
if [ $level -le $LOGLEVEL ]; then
return 0
fi
return 1
}
function error() {
log $ERROR "$@"
}
function isError() {
isLevel $ERROR
}
function warn() {
log $WARN "$@"
}
function isWarn() {
isLevel $WARN
}
function info() {
log $INFO "$@"
}
function isInfo() {
isLevel $INFO
}
function debug() {
log $DEBUG "$@"
}
function isDebug() {
isLevel $DEBUG
}
function configOption() {
local namespace=$1
local name=$2
local value=$3
echo "{\"Namespace\":\"$namespace\",\"OptionName\":\"$name\",\"Value\":\"$value\"}"
}
function configure() {
local separator=","
while getopts "n" OPT $@; do
case "$OPT" in
n) separator=""
esac
done
# reset index, remove parsed args
optind=$OPTIND
unset OPTIND
if [ "$optind" -gt 0 ]; then
shift $((optind - 1))
fi
local file=$1
local namespace=$2
local name=$3
local value=$4
if [ -n "$value" ]; then
echo $(configOption "$namespace" "$name" "$value") $separator >> "$file"
fi
}
######################################################################
# parse options
while getopts "a:e:f:d:D:i:T:k:t:hv:Vqo:1:2:3:4:5:j:g:c:C:m:M:" OPT $@; do
case "$OPT" in
h) usage; exit 0;;
v) LOGLEVEL=$((LOGLEVEL + 1));;
q) LOGLEVEL=$((LOGLEVEL - 1));;
a) APP="$OPTARG";;
f) APPFILE="$OPTARG";;
# environment name
e) ENV="$OPTARG";;
d) APPDESCR="$OPTARG";;
D) ENVDESCR="$OPTARG";;
i) IMAGEID="$OPTARG";;
t) INSTANCETYPE="$OPTARG";;
V) VERSION="$OPTARG";;
k) KEYNAME="$OPTARG";;
T) TMPL="$OPTARG";;
o) OPTFILE="$OPTARG";;
# application parameters
1) PARAM1="$OPTARG";;
2) PARAM2="$OPTARG";;
3) PARAM3="$OPTARG";;
4) PARAM4="$OPTARG";;
5) PARAM5="$OPTARG";;
j) JDBC_CONNECTION_STRING="$OPTARG";;
g) SECGROUP="$OPTARG";;
c) CNAME="$OPTARG";;
# min, max instance count
m) MAX_COUNT="$OPTARG";;
M) MIN_COUNT="$OPTARG";;
# container
C) CONTAINER="$OPTARG";;
esac
done
# reset index, remove parsed args
optind=$OPTIND
unset OPTIND
if [ "$optind" -gt 0 ]; then
shift $((optind - 1))
fi
######################################################################
# validate args
# app name is required
if [ -z "$APP" ]; then
error "missing app name (paramater -a)"
exit 10
fi
if [ -z "$APPDESCR" ]; then
APPDESCR="$APP"
fi
# environment and/or template is required
if [ -z "$ENV" ]; then
if [ -z "$TMPL" ]; then
#error "missing environment or template name (paramater -e or -T)"
#exit 10
TMPL="$DEFAULT_TEMPLATE_NAME" # default configuration name is "Default"
fi
else
if [ -z "$TMPL" ]; then
# use environment name as template name
#TMPL="$ENV"
TMPL="$DEFAULT_TEMPLATE_NAME" # default configuration name is "Default"
fi
if [ -z "$CNAME" ]; then
CNAME="$ENV"
fi
fi
if [ -z "$ENVDESCR" ]; then
ENVDESCR="$ENV"
fi
if [ -z "$ENVDESCR" ]; then
ENVDESCR="$TMPL"
fi
# version is optional
if [ -z "$VERSION" ]; then
#VERSION=initial
VERSION=$(date +%Y%m%d-%H%M%S)
fi
# allow to choose between 32bit and 64 bit Tomcat container
case "$CONTAINER" in
64) CONTAINER="64bit Amazon Linux running Tomcat 6";;
32) CONTAINER="32bit Amazon Linux running Tomcat 6";;
esac
######################################################################
# perform actions
# check name of keypair
if [ -n "$KEYNAME" ]; then
# check whether ec2-describe-keypairs is available
if which ec2-describe-keypairs >/dev/null 2>&1 ; then
if ec2-describe-keypairs "$KEYNAME" >/dev/null 2>&1; then
debug "keypair $KEYNAME is valid"
else
error "keypair $KEYNAME does not exist"
exit 10
fi
fi
fi
# check whether application already exists
appCheck=$(elastic-beanstalk-describe-applications -a "$APP" | grep -iv "No applications found")
if [ -z "$appCheck" ]; then
info "creating app $APP"
elastic-beanstalk-create-application -a "$APP" -d "$APPDESCR"
RC=$?
debug "result of elastic-beanstalk-create-application: $RC"
if [ "$RC" -ne 0 ]; then
echo "failed to create application $APP"
exit $RC
fi
else
info "app $APP already exists"
fi
if [ -n "$APPFILE" -o -n "$VERSION" ]; then
# check whether app version already exists:
# list version (and remove headers and "no such version" warning)
versions=$(elastic-beanstalk-describe-application-versions -a "$APP" -l "$VERSION" | grep -Ev "were found|----|DateCreated")
if [ -z "$versions" ]; then
info "creating app $APP version $VERSION from ${APPFILE:-AWS sample application}"
# check whether APPFILE is a local file instead of S3 location
if [ -f "$APPFILE" ]; then
warn "$APPFILE is a local file, but a S3 location formatted as 'bucket/file_key' is expected!"
fi
elastic-beanstalk-create-application-version -a "$APP" -l "$VERSION" -s "$APPFILE"
RC=$?
debug "result of elastic-beanstalk-create-application-version: $RC"
if [ "$RC" -ne 0 ]; then
echo "failed to create application $APP version $VERSION from $APPFILE"
exit $RC
fi
else
# TODO update version if location differs
info "app $APP version $VERSION already exists"
fi
fi
# create temporary options file
TMPOPTFILE=`mktemp -p "$TMPDIR" launcfg.XXXXXXX`
debug "create temporary options file in $TMPOPTFILE"
# open options array
echo "[" > "$TMPOPTFILE"
if [ -f "$OPTFILE" ]; then
# add existing user options
cat "$OPTFILE" >> "$TMPOPTFILE"
fi
configure "$TMPOPTFILE" "aws:autoscaling:launchconfiguration" "ImageId" "$IMAGEID"
configure "$TMPOPTFILE" "aws:autoscaling:launchconfiguration" "SecurityGroups" "$SECGROUP"
configure "$TMPOPTFILE" "aws:autoscaling:launchconfiguration" "InstanceType" "$INSTANCETYPE"
configure "$TMPOPTFILE" "aws:autoscaling:launchconfiguration" "EC2KeyName" "$KEYNAME"
configure "$TMPOPTFILE" "aws:elasticbeanstalk:application:environment" "PARAM1" "$PARAM1"
configure "$TMPOPTFILE" "aws:elasticbeanstalk:application:environment" "PARAM2" "$PARAM2"
configure "$TMPOPTFILE" "aws:elasticbeanstalk:application:environment" "PARAM3" "$PARAM3"
configure "$TMPOPTFILE" "aws:elasticbeanstalk:application:environment" "PARAM4" "$PARAM4"
configure "$TMPOPTFILE" "aws:elasticbeanstalk:application:environment" "PARAM5" "$PARAM5"
configure "$TMPOPTFILE" "aws:elasticbeanstalk:application:environment" "JDBC_CONNECTION_STRING" "$JDBC_CONNECTION_STRING"
configure "$TMPOPTFILE" "aws:autoscaling:asg" "MaxSize" "$MAX_COUNT"
# add final param without trailing comma
configure -n "$TMPOPTFILE" "aws:autoscaling:asg" "MinSize" "$MIN_COUNT"
# close options array
echo "]" >> "$TMPOPTFILE"
# check whether app version already exists:
# NOTE we abuse elastic-beanstalk-describe-configuration-settings to check, whether the configuration template exists
templateCheck=$(elastic-beanstalk-describe-configuration-settings -a "$APP" -t "$TMPL"|head -1|grep -i "error")
if [ -n "$templateCheck" ]; then
info "creating configuration template $TMPL"
# error, create configuration template
if [ -n "$CONTAINER" ]; then
elastic-beanstalk-create-configuration-template -a "$APP" -t "$TMPL" -d "$ENVDESCR" -f "$TMPOPTFILE" -s "$CONTAINER"
else
elastic-beanstalk-create-configuration-template -a "$APP" -t "$TMPL" -d "$ENVDESCR" -f "$TMPOPTFILE"
fi
else
info "updating existing configuration template $TMPL"
# configuration template already exists, update it
if [ -n "$CONTAINER" ]; then
warn "cannot update solution stack for existing configuration template ($CONTAINER)"
fi
elastic-beanstalk-update-configuration-template -a "$APP" -t "$TMPL" -d "$ENVDESCR" -f "$TMPOPTFILE"
fi
RC=$?
debug "result of elastic-beanstalk-create-configuration-template: $RC"
# delete temporary options file
if [ -n "$TMPOPTFILE" -a -f "$TMPOPTFILE" ]; then
if isDebug; then
debug "options"
cat "$TMPOPTFILE"
fi
rm -f "$TMPOPTFILE"
fi
if [ "$RC" -ne 0 ]; then
error "failed to create configuration template"
exit $RC
fi
if [ -n "$ENV" ]; then
# check availablility of CNAME
checkDNS=$(elastic-beanstalk-check-dns-availability -c "$CNAME" | tail -1 | grep -i "true")
if [ -n "$checkDNS" ]; then
info "creating environment $ENV for app $APP version $VERSION"
elastic-beanstalk-create-environment -a "$APP" -l "$VERSION" -e "$ENV" -t "$TMPL" -c "$CNAME" -d "$ENVDESCR"
else
error "failed to create environment $ENV for app $APP version $VERSION: CNAME $CNAME is not available"
fi
fi
exit $RC
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment