Created
February 3, 2011 02:43
-
-
Save jetztgradnet/808948 to your computer and use it in GitHub Desktop.
Script to start an Amazon ElasticBeanstalk application with configuration parameters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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