Skip to content

Commit

Permalink
Added support for getting tag name from environment variable
Browse files Browse the repository at this point in the history
  • Loading branch information
Phillip Shipley committed Oct 9, 2015
2 parents 8132901 + f293b04 commit e519ce3
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 20 deletions.
35 changes: 30 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,17 @@ Usage

Optional arguments:
-t | --timeout Default is 90s. Script monitors ECS Service for new task definition to be running.
-e | --tag-env-var Get image tag name from environment variable. If provided this will override value specified in image name argument.
-v | --verbose Verbose output

Example:
ecs-deploy -k ABC123 -s SECRETKEY -c production1 -n doorman-service -i docker.repo.com/doorman:latest
Examples:
Simple (Using env vars for AWS settings):

ecs-deploy -c production1 -n doorman-service -i docker.repo.com/doorman:latest

All options:

ecs-deploy -k ABC123 -s SECRETKEY -r us-east-1 -c production1 -n doorman-service -i docker.repo.com/doorman -t 240 -e CI_TIMESTAMP -v

How it works
------------
Expand Down Expand Up @@ -72,19 +80,36 @@ be an unlikely use case._
This behavior allows two possible process to specify which images, and therefore which configurations, to deploy. First, you
may set the tag to always be `latest` (or some other static value), like so:

ecs-deploy XXXXX XXXXX us-east-1 default my_task_def my_app my.private.repo.com/frontend_container:lastest
ecs-deploy -c CLUSTERNAME -n SERVICENAME -i my.private.repo.com/frontend_container:lastest

This will result in identical new versions of the Task Definition being created, but the Service will still do a blue/green
deployment, and will so will pull down the latest version (if you previously pushed it into the registry).

Alternatively, you may specify some other means of obtaining the tag, since the script `eval`s the image string. You could use
git tags as a map to docker tags:

ecs-deploy XXXXX XXXXX us-east-1 default my_task_def my_app 'my.private.repo.com/frontend_container:`git describe`'
ecs-deploy -c CLUSTERNAME -n SERVICENAME -i 'my.private.repo.com/frontend_container:`git describe`'

Or perhaps just obtain read the docker tag from another file in your development:

ecs-deploy XXXXX XXXXX us-east-1 default my_task_def my_app 'my.private.repo.com/frontend_container:$(< VERSION)'
ecs-deploy -c CLUSTERNAME -n SERVICENAME -i 'my.private.repo.com/frontend_container:$(< VERSION)'

In any case, just make sure your process builds, tags, and pushes the docker image you use to the repository before running
this script.

Use Environment Variable for tag name value
-------------------------------------------
In some cases you may want to use an environment variable for the tag name of your image.
For instance, we use Codeship for continous integration and deployment. In their Docker
environment they can build images and tag them with different variables, such as
the current unix timestamp. We want to use these unique and changing values for image tags
so that each task definition refers to a unique docker image/tag. This gives us the
ability to revert/rollback changes by just selecting a previous task definition and
updating the service. We plan to add a revert command/option to ecs-deploy to simplify this further.

Using the ```-e``` argument you can provide the name of an environment variable that
holds the value you wish to use for the tag. On Codeship they set an env var named CI_TIMESTAMP.

So we use ```ecs-deploy``` like this:

ecs-deploy -c production1 -n doorman-api -i my.private.repo/doorman-api -e CI_TIMESTAMP
59 changes: 44 additions & 15 deletions ecs-deploy
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,17 @@ function usage() {
Optional arguments:
-t | --timeout Default is 90s. Script monitors ECS Service for new task definition to be running.
-e | --tag-env-var Get image tag name from environment variable. If provided this will override value specified in image name argument.
-v | --verbose Verbose output
Example:
ecs-deploy -k ABC123 -s SECRETKEY -c production1 -n doorman-service -i docker.repo.com/doorman:latest
Examples:
Simple (Using env vars for AWS settings):
ecs-deploy -c production1 -n doorman-service -i docker.repo.com/doorman:latest
All options:
ecs-deploy -k ABC123 -s SECRETKEY -r us-east-1 -c production1 -n doorman-service -i docker.repo.com/doorman -t 240 -e CI_TIMESTAMP -v
EOM

Expand All @@ -34,8 +42,9 @@ SERVICE=false
IMAGE=false
TIMEOUT=90
VERBOSE=false
TAGVAR=false

# AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY can be set as environment variables
# AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY can be set as environment variables
if [ -z ${AWS_ACCESS_KEY_ID+x} ]; then AWS_ACCESS_KEY_ID=false; fi
if [ -z ${AWS_SECRET_ACCESS_KEY+x} ]; then AWS_SECRET_ACCESS_KEY=false; fi

Expand Down Expand Up @@ -69,6 +78,10 @@ do
TIMEOUT="$2"
shift
;;
-e|--tag-env-var)
TAGVAR="$2"
shift
;;
-v|--verbose)
VERBOSE=true
;;
Expand All @@ -85,23 +98,23 @@ if [ $VERBOSE == true ]; then
fi

# Make sure we have all the variables needed: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, CLUSTER, SERVICE, IMAGE
if [ $AWS_ACCESS_KEY_ID == false ]; then
if [ $AWS_ACCESS_KEY_ID == false ]; then
echo "AWS_ACCESS_KEY_ID is required. You can set it as an environment variable or pass the value using -k or --aws-access-key"
exit 1
fi
if [ $AWS_SECRET_ACCESS_KEY == false ]; then
if [ $AWS_SECRET_ACCESS_KEY == false ]; then
echo "AWS_SECRET_ACCESS_KEY is required. You can set it as an environment variable or pass the value using -s or --aws-secret-key"
exit 1
fi
if [ $CLUSTER == false ]; then
if [ $CLUSTER == false ]; then
echo "CLUSTER is required. You can pass the value using -c or --cluster"
exit 1
fi
if [ $SERVICE == false ]; then
if [ $SERVICE == false ]; then
echo "SERVICE is required. You can pass the value using -n or --service-name"
exit 1
fi
if [ $IMAGE == false ]; then
if [ $IMAGE == false ]; then
echo "IMAGE is required. You can pass the value using -i or --image"
exit 1
fi
Expand All @@ -115,13 +128,30 @@ aws ecs describe-task-definition --task-def $TASK_DEFINITION > def

# Extract the image from its tag
if [[ $IMAGE =~ ^[^:]+:[^:/]+$ ]]; then
# Image with format registry/repo:tag
im=`echo $IMAGE | cut -d':' -f 1`
tag=`echo $IMAGE | cut -d':' -f 2`
elif [[ $IMAGE =~ ^[^:]+/[^:]+$ ]]; then
# Image with format registry/repo (no tag specified)
im=`echo $IMAGE | cut -d':' -f 1`
elif [[ $IMAGE =~ ^[^:]+:[^:]+:[^:]+$ ]]; then
# Image with format registry:port/repo:tag
im=`echo $IMAGE | cut -d':' -f 1,2`
tag=`echo $IMAGE | cut -d':' -f 3`
elif [[ $IMAGE =~ ^[^:/]+:[^:]+/[^:]+$ ]]; then
# Image with format registry:port/repo (no tag specified)
im=`echo $IMAGE | cut -d':' -f 1,2`
else
echo "You must specify an image with a tag" && exit 1;
echo "Unable to parse image name: $IMAGE, check the format and try again" && exit 1
fi

# Tag was not found in image name
if [[ -n $tag ]]; then
# Get tag name value from ENV var
tag=${!TAGVAR}
if [[ "x$tag" == "x" ]]; then
echo "The ENV var named $TAGNAME is empty or not set" && exit 1;
fi
fi

# Extract out the registry (and possibly repository) from the image, if applicable
Expand Down Expand Up @@ -163,30 +193,29 @@ UPDATE=`aws ecs update-service --cluster $CLUSTER --service $SERVICE --task-defi
# See if the service is able to come up again
every=10
i=0
while [ $i -lt $TIMEOUT ]
while [ $i -lt $TIMEOUT ]
do
# Scan the list of running tasks for that service, and see if one of them is the
# new version of the task definition
rm -f tasks

aws ecs list-tasks --cluster $CLUSTER --service-name $SERVICE --desired-status RUNNING \
| jq '.taskArns[]' \
| xargs -I{} aws ecs describe-tasks --cluster $CLUSTER --tasks {} >> tasks

jq < tasks > results ".tasks[]| if .taskDefinitionArn == \"$NEW_TASKDEF\" then . else empty end|.lastStatus"

RUNNING=`grep -e "RUNNING" results`

if [ $RUNNING ]; then
echo "Service updated successfully, new task definition running.";
exit 0
fi

sleep $every
i=$(( $i + $every ))
done

# Timeout
echo "ERROR: New task definition not running within $TIMEOUT seconds"
exit 1

0 comments on commit e519ce3

Please sign in to comment.