existing scripts
This commit is contained in:
commit
7f41e66b32
4 changed files with 818 additions and 0 deletions
BIN
.DS_Store
vendored
Normal file
BIN
.DS_Store
vendored
Normal file
Binary file not shown.
6
bin/backslash-key-remap-fix.sh
Executable file
6
bin/backslash-key-remap-fix.sh
Executable file
|
|
@ -0,0 +1,6 @@
|
|||
#/bin/sh -e
|
||||
|
||||
hidutil property --set '{"UserKeyMapping":
|
||||
[{"HIDKeyboardModifierMappingSrc":0x700000064,
|
||||
"HIDKeyboardModifierMappingDst":0x700000035}]
|
||||
}'
|
||||
807
bin/ecs-deploy
Executable file
807
bin/ecs-deploy
Executable file
|
|
@ -0,0 +1,807 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Setup default values for variables
|
||||
VERSION="3.10.6"
|
||||
CLUSTER=false
|
||||
SERVICE=false
|
||||
TASK_DEFINITION=false
|
||||
TASK_DEFINITION_FILE=false
|
||||
MAX_DEFINITIONS=0
|
||||
AWS_ASSUME_ROLE=false
|
||||
IMAGE=false
|
||||
MIN=false
|
||||
MAX=false
|
||||
TIMEOUT=90
|
||||
VERBOSE=false
|
||||
TAGVAR=false
|
||||
TAGONLY=""
|
||||
ENABLE_ROLLBACK=false
|
||||
USE_MOST_RECENT_TASK_DEFINITION=false
|
||||
AWS_CLI=$(which aws)
|
||||
AWS_ECS="$AWS_CLI --output json ecs"
|
||||
FORCE_NEW_DEPLOYMENT=false
|
||||
SKIP_DEPLOYMENTS_CHECK=false
|
||||
RUN_TASK=false
|
||||
RUN_TASK_LAUNCH_TYPE=false
|
||||
RUN_TASK_PLATFORM_VERSION=false
|
||||
RUN_TASK_NETWORK_CONFIGURATION=false
|
||||
RUN_TASK_WAIT_FOR_SUCCESS=false
|
||||
TASK_DEFINITION_TAGS=false
|
||||
COPY_TASK_DEFINITION_TAGS=false
|
||||
|
||||
function usage() {
|
||||
cat <<EOM
|
||||
##### ecs-deploy #####
|
||||
Simple script for triggering blue/green deployments on Amazon Elastic Container Service
|
||||
https://github.com/silinternational/ecs-deploy
|
||||
|
||||
One of the following is required:
|
||||
-n | --service-name Name of service to deploy
|
||||
-d | --task-definition Name of task definition to deploy
|
||||
|
||||
Required arguments:
|
||||
-k | --aws-access-key AWS Access Key ID. May also be set as environment variable AWS_ACCESS_KEY_ID
|
||||
-s | --aws-secret-key AWS Secret Access Key. May also be set as environment variable AWS_SECRET_ACCESS_KEY
|
||||
-r | --region AWS Region Name. May also be set as environment variable AWS_DEFAULT_REGION
|
||||
-p | --profile AWS Profile to use - If you set this aws-access-key, aws-secret-key and region are needed
|
||||
-c | --cluster Name of ECS cluster
|
||||
-i | --image Name of Docker image to run, ex: repo/image:latest
|
||||
Format: [domain][:port][/repo][/][image][:tag]
|
||||
Examples: mariadb, mariadb:latest, silintl/mariadb,
|
||||
silintl/mariadb:latest, private.registry.com:8000/repo/image:tag
|
||||
--aws-instance-profile Use the IAM role associated with this instance
|
||||
|
||||
Optional arguments:
|
||||
-a | --aws-assume-role ARN for AWS Role to assume for ecs-deploy operations.
|
||||
-D | --desired-count The number of instantiations of the task to place and keep running in your service.
|
||||
-m | --min minumumHealthyPercent: The lower limit on the number of running tasks during a deployment.
|
||||
-M | --max maximumPercent: The upper limit on the number of running tasks during a deployment.
|
||||
-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.
|
||||
-to | --tag-only New tag to apply to all images defined in the task (multi-container task).
|
||||
If provided this will override value specified in image name argument.
|
||||
--max-definitions Number of Task Definition Revisions to persist before deregistering oldest revisions.
|
||||
--task-definition-file File used as task definition to deploy
|
||||
--enable-rollback Rollback task definition if new version is not running before TIMEOUT
|
||||
--force-new-deployment Force a new deployment of the service. Default is false.
|
||||
--use-latest-task-def Will use the most recently created task definition as it's base, rather than the last used.
|
||||
--skip-deployments-check Skip deployments check for services that take too long to drain old tasks
|
||||
--run-task Run created task now. If you set this, service-name are not needed.
|
||||
--wait-for-success Wait for task execution to complete and to receive the exitCode 0.
|
||||
--launch-type The launch type on which to run your task.
|
||||
(https://docs.aws.amazon.com/cli/latest/reference/ecs/run-task.html)
|
||||
--platform-version The Fargate platform version on which to run your task.
|
||||
(https://docs.aws.amazon.com/cli/latest/reference/ecs/run-task.html)
|
||||
--network-configuration The network configuration for the task. This parameter is required for task definitions that use
|
||||
the awsvpc network mode to receive their own elastic network interface, and it is not supported
|
||||
for other network modes. (https://docs.aws.amazon.com/cli/latest/reference/ecs/run-task.html)
|
||||
--copy-task-definition-tags Copy the existing task definition tags to the new task definition revision
|
||||
-v | --verbose Verbose output
|
||||
--version Display the version
|
||||
|
||||
Requirements:
|
||||
aws: AWS Command Line Interface
|
||||
jq: Command-line JSON processor
|
||||
|
||||
Examples:
|
||||
Simple deployment of a service (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
|
||||
|
||||
Updating a task definition with a new image:
|
||||
|
||||
ecs-deploy -d open-door-task -i docker.repo.com/doorman:17
|
||||
|
||||
Using profiles (for STS delegated credentials, for instance):
|
||||
|
||||
ecs-deploy -p PROFILE -c production1 -n doorman-service -i docker.repo.com/doorman -t 240 -e CI_TIMESTAMP -v
|
||||
|
||||
Update just the tag on whatever image is found in ECS Task (supports multi-container tasks):
|
||||
|
||||
ecs-deploy -c staging -n core-service -to 0.1.899 -i ignore
|
||||
|
||||
Notes:
|
||||
- If a tag is not found in image and an ENV var is not used via -e and a tag is not provided with -to, it will default the tag to "latest"
|
||||
EOM
|
||||
|
||||
exit 3
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
# Check requirements
|
||||
function require() {
|
||||
command -v "$1" > /dev/null 2>&1 || {
|
||||
echo "Some of the required software is not installed:"
|
||||
echo " please install $1" >&2;
|
||||
exit 4;
|
||||
}
|
||||
}
|
||||
|
||||
function assumeRole() {
|
||||
|
||||
temp_role=$(aws sts assume-role \
|
||||
--role-arn "${AWS_ASSUME_ROLE}" \
|
||||
--role-session-name "$(date +"%s")")
|
||||
|
||||
export AWS_ACCESS_KEY_ID=$(echo $temp_role | jq .Credentials.AccessKeyId | xargs)
|
||||
export AWS_SECRET_ACCESS_KEY=$(echo $temp_role | jq .Credentials.SecretAccessKey | xargs)
|
||||
export AWS_SESSION_TOKEN=$(echo $temp_role | jq .Credentials.SessionToken | xargs)
|
||||
}
|
||||
|
||||
|
||||
function assumeRoleClean() {
|
||||
unset AWS_ACCESS_KEY_ID
|
||||
unset AWS_SECRET_ACCESS_KEY
|
||||
unset AWS_SESSION_TOKEN
|
||||
}
|
||||
|
||||
|
||||
# Check that all required variables/combinations are set
|
||||
function assertRequiredArgumentsSet() {
|
||||
|
||||
# AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGION and AWS_PROFILE can be set as environment variables
|
||||
if [ -z ${AWS_ACCESS_KEY_ID+x} ]; then unset AWS_ACCESS_KEY_ID; fi
|
||||
if [ -z ${AWS_SECRET_ACCESS_KEY+x} ]; then unset AWS_SECRET_ACCESS_KEY; fi
|
||||
if [ -z ${AWS_DEFAULT_REGION+x} ];
|
||||
then unset AWS_DEFAULT_REGION
|
||||
else
|
||||
AWS_ECS="$AWS_ECS --region $AWS_DEFAULT_REGION"
|
||||
fi
|
||||
if [ -z ${AWS_PROFILE+x} ];
|
||||
then unset AWS_PROFILE
|
||||
else
|
||||
AWS_ECS="$AWS_ECS --profile $AWS_PROFILE"
|
||||
fi
|
||||
|
||||
if [ $SERVICE == false ] && [ $TASK_DEFINITION == false ]; then
|
||||
echo "One of SERVICE or TASK DEFINITION is required. You can pass the value using -n / --service-name for a service, or -d / --task-definition for a task"
|
||||
exit 5
|
||||
fi
|
||||
if [ $SERVICE != false ] && [ $TASK_DEFINITION != false ]; then
|
||||
echo "Only one of SERVICE or TASK DEFINITION may be specified, but you supplied both"
|
||||
exit 6
|
||||
fi
|
||||
if [ $SERVICE != false ] && [ $CLUSTER == false ]; then
|
||||
echo "CLUSTER is required. You can pass the value using -c or --cluster"
|
||||
exit 7
|
||||
fi
|
||||
if [ $IMAGE == false ] && [ $FORCE_NEW_DEPLOYMENT == false ]; then
|
||||
echo "IMAGE is required. You can pass the value using -i or --image"
|
||||
exit 8
|
||||
fi
|
||||
if ! [[ $MAX_DEFINITIONS =~ ^-?[0-9]+$ ]]; then
|
||||
echo "MAX_DEFINITIONS must be numeric, or not defined."
|
||||
exit 9
|
||||
fi
|
||||
|
||||
if [ $RUN_TASK == false ] && [ $RUN_TASK_LAUNCH_TYPE != false ]; then
|
||||
echo 'LAUNCH TYPE requires setting RUN TASK argument. You can set it using --run-task flag.'
|
||||
exit 10
|
||||
fi
|
||||
|
||||
if [ $RUN_TASK == false ] && [ $RUN_TASK_NETWORK_CONFIGURATION != false ]; then
|
||||
echo 'NETWORK CONFIGURATION requires setting RUN TASK argument. You can set it using --run-task flag.'
|
||||
exit 11
|
||||
fi
|
||||
|
||||
if [ $RUN_TASK == false ] && [ $RUN_TASK_WAIT_FOR_SUCCESS != false ]; then
|
||||
echo 'WAIT FOR SUCCESS requires setting RUN TASK argument. You can set it using --run-task flag.'
|
||||
exit 11
|
||||
fi
|
||||
|
||||
if [ $RUN_TASK == false ] && [ $RUN_TASK_PLATFORM_VERSION != false ]; then
|
||||
echo 'PLATFORM VERSION requires setting RUN TASK argument. You can set it using --run-task flag.'
|
||||
exit 12
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
function parseImageName() {
|
||||
|
||||
# Define regex for image name
|
||||
# This regex will create groups for:
|
||||
# - domain
|
||||
# - port
|
||||
# - repo
|
||||
# - image
|
||||
# - tag
|
||||
# If a group is missing it will be an empty string
|
||||
if [[ "x$TAGONLY" == "x" ]]; then
|
||||
imageRegex="^([a-zA-Z0-9\.\-]+):?([0-9]+)?/([a-zA-Z0-9\._\-]+)(/[\/a-zA-Z0-9\._\-]+)?:?([a-zA-Z0-9\._\-]+)?$"
|
||||
else
|
||||
imageRegex="^:?([a-zA-Z0-9\._-]+)?$"
|
||||
fi
|
||||
|
||||
if [[ $IMAGE =~ $imageRegex ]]; then
|
||||
# Define variables from matching groups
|
||||
if [[ "x$TAGONLY" == "x" ]]; then
|
||||
domain=${BASH_REMATCH[1]}
|
||||
port=${BASH_REMATCH[2]}
|
||||
repo=${BASH_REMATCH[3]}
|
||||
img=${BASH_REMATCH[4]/#\//}
|
||||
tag=${BASH_REMATCH[5]}
|
||||
|
||||
# Validate what we received to make sure we have the pieces needed
|
||||
if [[ "x$domain" == "x" ]]; then
|
||||
echo "Image name does not contain a domain or repo as expected. See usage for supported formats."
|
||||
exit 10;
|
||||
fi
|
||||
if [[ "x$repo" == "x" ]]; then
|
||||
echo "Image name is missing the actual image name. See usage for supported formats."
|
||||
exit 11;
|
||||
fi
|
||||
|
||||
# When a match for image is not found, the image name was picked up by the repo group, so reset variables
|
||||
if [[ "x$img" == "x" ]]; then
|
||||
img=$repo
|
||||
repo=""
|
||||
fi
|
||||
else
|
||||
tag=${BASH_REMATCH[1]}
|
||||
domain=""
|
||||
port=""
|
||||
repo=""
|
||||
img=""
|
||||
fi
|
||||
else
|
||||
# check if using root level repo with format like mariadb or mariadb:latest
|
||||
rootRepoRegex="^([a-zA-Z0-9\-]+):?([a-zA-Z0-9\.\-]+)?$"
|
||||
if [[ $IMAGE =~ $rootRepoRegex ]]; then
|
||||
img=${BASH_REMATCH[1]}
|
||||
if [[ "x$img" == "x" ]]; then
|
||||
echo "Invalid image name. See usage for supported formats."
|
||||
exit 12
|
||||
fi
|
||||
tag=${BASH_REMATCH[2]}
|
||||
|
||||
# for root level repo, initialize unused variables for checks when rebuilding image below
|
||||
domain=""
|
||||
port=""
|
||||
repo=""
|
||||
|
||||
else
|
||||
echo "Unable to parse image name: $IMAGE, check the format and try again"
|
||||
exit 13
|
||||
fi
|
||||
fi
|
||||
|
||||
# If tag is missing make sure we can get it from env var, or use latest as default
|
||||
if [[ "x$tag" == "x" ]]; then
|
||||
if [[ $TAGVAR == false ]]; then
|
||||
tag="latest"
|
||||
else
|
||||
tag=${!TAGVAR}
|
||||
if [[ "x$tag" == "x" ]]; then
|
||||
tag="latest"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Reassemble image name
|
||||
useImage=""
|
||||
if [[ "x$TAGONLY" == "x" ]]; then
|
||||
|
||||
if [[ ! -z "$domain" ]]; then
|
||||
useImage="$domain"
|
||||
fi
|
||||
if [[ ! -z "$port" ]]; then
|
||||
useImage="$useImage:$port"
|
||||
fi
|
||||
if [[ ! -z "$repo" ]]; then
|
||||
useImage="$useImage/$repo"
|
||||
fi
|
||||
if [[ ! -z "$img" ]]; then
|
||||
if [[ -z "$useImage" ]]; then
|
||||
useImage="$img"
|
||||
else
|
||||
useImage="$useImage/$img"
|
||||
fi
|
||||
fi
|
||||
imageWithoutTag="$useImage"
|
||||
if [[ ! -z "$tag" ]]; then
|
||||
useImage="$useImage:$tag"
|
||||
fi
|
||||
|
||||
else
|
||||
useImage="$TAGONLY"
|
||||
fi
|
||||
|
||||
# If in test mode output $useImage
|
||||
if [ "$BASH_SOURCE" != "$0" ]; then
|
||||
echo $useImage
|
||||
fi
|
||||
}
|
||||
|
||||
function getCurrentTaskDefinition() {
|
||||
if [ $SERVICE != false ]; then
|
||||
# Get current task definition arn from service
|
||||
TASK_DEFINITION_ARN=`$AWS_ECS describe-services --services $SERVICE --cluster $CLUSTER | jq -r .services[0].taskDefinition`
|
||||
TASK_DEFINITION=`$AWS_ECS describe-task-definition --task-def $TASK_DEFINITION_ARN`
|
||||
|
||||
# For rollbacks
|
||||
LAST_USED_TASK_DEFINITION_ARN=$TASK_DEFINITION_ARN
|
||||
|
||||
if [ $USE_MOST_RECENT_TASK_DEFINITION != false ]; then
|
||||
# Use the most recently created TD of the family; rather than the most recently used.
|
||||
TASK_DEFINITION_FAMILY=`$AWS_ECS describe-task-definition --task-def $TASK_DEFINITION_ARN | jq -r .taskDefinition.family`
|
||||
TASK_DEFINITION=`$AWS_ECS describe-task-definition --task-def $TASK_DEFINITION_FAMILY`
|
||||
TASK_DEFINITION_ARN=`$AWS_ECS describe-task-definition --task-def $TASK_DEFINITION_FAMILY | jq -r .taskDefinition.taskDefinitionArn`
|
||||
fi
|
||||
elif [ $TASK_DEFINITION != false ]; then
|
||||
# Get current task definition arn from family[:revision] (or arn)
|
||||
TASK_DEFINITION_ARN=`$AWS_ECS describe-task-definition --task-def $TASK_DEFINITION | jq -r .taskDefinition.taskDefinitionArn`
|
||||
fi
|
||||
|
||||
# Get task definition using current task definition arn
|
||||
# If we're copying task definition tags to the new revision, also get current task definition tags
|
||||
if [[ "$COPY_TASK_DEFINITION_TAGS" == true ]]; then
|
||||
TASK_DEFINITION=`$AWS_ECS describe-task-definition --task-def $TASK_DEFINITION_ARN --include TAGS`
|
||||
TASK_DEFINITION_TAGS=$( echo "$TASK_DEFINITION" | jq ".tags" )
|
||||
else
|
||||
TASK_DEFINITION=`$AWS_ECS describe-task-definition --task-def $TASK_DEFINITION_ARN`
|
||||
fi
|
||||
}
|
||||
|
||||
function createNewTaskDefJson() {
|
||||
|
||||
if [ $TASK_DEFINITION_FILE == false ]; then
|
||||
taskDefinition="$TASK_DEFINITION"
|
||||
else
|
||||
taskDefinition="$(cat $TASK_DEFINITION_FILE)"
|
||||
fi
|
||||
|
||||
# Get a JSON representation of the current task definition
|
||||
# + Update definition to use new image name
|
||||
# + Filter the def
|
||||
if [[ "x$TAGONLY" == "x" ]]; then
|
||||
DEF=$( echo "$taskDefinition" \
|
||||
| sed -e 's~"image":.*'"${imageWithoutTag}"'.*,~"image": "'"${useImage}"'",~g' \
|
||||
| jq '.taskDefinition' )
|
||||
else
|
||||
DEF=$( echo "$taskDefinition" \
|
||||
| sed -e "s|\(\"image\": *\".*:\)\(.*\)\"|\1${useImage}\"|g" \
|
||||
| jq '.taskDefinition' )
|
||||
fi
|
||||
|
||||
# Default JQ filter for new task definition
|
||||
NEW_DEF_JQ_FILTER="family: .family, volumes: .volumes, containerDefinitions: .containerDefinitions, placementConstraints: .placementConstraints"
|
||||
|
||||
# Some options in task definition should only be included in new definition if present in
|
||||
# current definition. If found in current definition, append to JQ filter.
|
||||
CONDITIONAL_OPTIONS=(networkMode taskRoleArn placementConstraints executionRoleArn)
|
||||
for i in "${CONDITIONAL_OPTIONS[@]}"; do
|
||||
re=".*${i}.*"
|
||||
if [[ "$DEF" =~ $re ]]; then
|
||||
NEW_DEF_JQ_FILTER="${NEW_DEF_JQ_FILTER}, ${i}: .${i}"
|
||||
fi
|
||||
done
|
||||
|
||||
# Updated jq filters for AWS Fargate
|
||||
REQUIRES_COMPATIBILITIES=$(echo "${DEF}" | jq -r '. | select(.requiresCompatibilities != null) | .requiresCompatibilities[]')
|
||||
if `echo ${REQUIRES_COMPATIBILITIES[@]} | grep -q "FARGATE"`; then
|
||||
FARGATE_JQ_FILTER='requiresCompatibilities: .requiresCompatibilities, cpu: .cpu, memory: .memory'
|
||||
|
||||
if [[ ! "$NEW_DEF_JQ_FILTER" =~ ".*executionRoleArn.*" ]]; then
|
||||
FARGATE_JQ_FILTER="${FARGATE_JQ_FILTER}, executionRoleArn: .executionRoleArn"
|
||||
fi
|
||||
NEW_DEF_JQ_FILTER="${NEW_DEF_JQ_FILTER}, ${FARGATE_JQ_FILTER}"
|
||||
fi
|
||||
|
||||
# Build new DEF with jq filter
|
||||
NEW_DEF=$(echo "$DEF" | jq "{${NEW_DEF_JQ_FILTER}}")
|
||||
|
||||
# If in test mode output $NEW_DEF
|
||||
if [ "$BASH_SOURCE" != "$0" ]; then
|
||||
echo "$NEW_DEF"
|
||||
fi
|
||||
}
|
||||
|
||||
function registerNewTaskDefinition() {
|
||||
# Register the new task definition, and store its ARN
|
||||
if [[ "$COPY_TASK_DEFINITION_TAGS" == true && "$TASK_DEFINITION_TAGS" != false ]]; then
|
||||
NEW_TASKDEF=`$AWS_ECS register-task-definition --cli-input-json "$NEW_DEF" --tags "$TASK_DEFINITION_TAGS" | jq -r .taskDefinition.taskDefinitionArn`
|
||||
else
|
||||
NEW_TASKDEF=`$AWS_ECS register-task-definition --cli-input-json "$NEW_DEF" | jq -r .taskDefinition.taskDefinitionArn`
|
||||
fi
|
||||
}
|
||||
|
||||
function rollback() {
|
||||
echo "Rolling back to ${LAST_USED_TASK_DEFINITION_ARN}"
|
||||
$AWS_ECS update-service --cluster $CLUSTER --service $SERVICE --task-definition $LAST_USED_TASK_DEFINITION_ARN > /dev/null
|
||||
}
|
||||
|
||||
function updateServiceForceNewDeployment() {
|
||||
echo 'Force a new deployment of the service'
|
||||
$AWS_ECS update-service --cluster $CLUSTER --service $SERVICE --force-new-deployment > /dev/null
|
||||
}
|
||||
|
||||
function updateService() {
|
||||
if [[ $(echo ${NEW_DEF} | jq ".containerDefinitions[0].healthCheck != null") == true ]]; then
|
||||
checkFieldName="healthStatus"
|
||||
checkFieldValue='"HEALTHY"'
|
||||
else
|
||||
checkFieldName="lastStatus"
|
||||
checkFieldValue='"RUNNING"'
|
||||
fi
|
||||
|
||||
UPDATE_SERVICE_SUCCESS="false"
|
||||
DEPLOYMENT_CONFIG=""
|
||||
if [ $MAX != false ]; then
|
||||
DEPLOYMENT_CONFIG=",maximumPercent=$MAX"
|
||||
fi
|
||||
if [ $MIN != false ]; then
|
||||
DEPLOYMENT_CONFIG="$DEPLOYMENT_CONFIG,minimumHealthyPercent=$MIN"
|
||||
fi
|
||||
if [ ! -z "$DEPLOYMENT_CONFIG" ]; then
|
||||
DEPLOYMENT_CONFIG="--deployment-configuration ${DEPLOYMENT_CONFIG:1}"
|
||||
fi
|
||||
|
||||
DESIRED_COUNT=""
|
||||
if [ ! -z ${DESIRED+undefined-guard} ]; then
|
||||
DESIRED_COUNT="--desired-count $DESIRED"
|
||||
fi
|
||||
|
||||
# Update the service
|
||||
UPDATE=`$AWS_ECS update-service --cluster $CLUSTER --service $SERVICE $DESIRED_COUNT --task-definition $NEW_TASKDEF $DEPLOYMENT_CONFIG`
|
||||
|
||||
# Only excepts RUNNING state from services whose desired-count > 0
|
||||
SERVICE_DESIREDCOUNT=`$AWS_ECS describe-services --cluster $CLUSTER --service $SERVICE | jq '.services[]|.desiredCount'`
|
||||
if [ $SERVICE_DESIREDCOUNT -gt 0 ]; then
|
||||
# See if the service is able to come up again
|
||||
every=10
|
||||
i=0
|
||||
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
|
||||
|
||||
RUNNING_TASKS=$($AWS_ECS list-tasks --cluster "$CLUSTER" --service-name "$SERVICE" --desired-status RUNNING \
|
||||
| jq -r '.taskArns[]')
|
||||
|
||||
if [[ ! -z $RUNNING_TASKS ]] ; then
|
||||
RUNNING=$($AWS_ECS describe-tasks --cluster "$CLUSTER" --tasks $RUNNING_TASKS \
|
||||
| jq ".tasks[]| if .taskDefinitionArn == \"$NEW_TASKDEF\" then . else empty end|.${checkFieldName}" \
|
||||
| grep -e "${checkFieldValue}") || :
|
||||
|
||||
if [ "$RUNNING" ]; then
|
||||
echo "Service updated successfully, new task definition running.";
|
||||
|
||||
if [[ $MAX_DEFINITIONS -gt 0 ]]; then
|
||||
FAMILY_PREFIX=${TASK_DEFINITION_ARN##*:task-definition/}
|
||||
FAMILY_PREFIX=${FAMILY_PREFIX%*:[0-9]*}
|
||||
TASK_REVISIONS=`$AWS_ECS list-task-definitions --family-prefix $FAMILY_PREFIX --status ACTIVE --sort ASC`
|
||||
NUM_ACTIVE_REVISIONS=$(echo "$TASK_REVISIONS" | jq ".taskDefinitionArns|length")
|
||||
if [[ $NUM_ACTIVE_REVISIONS -gt $MAX_DEFINITIONS ]]; then
|
||||
LAST_OUTDATED_INDEX=$(($NUM_ACTIVE_REVISIONS - $MAX_DEFINITIONS - 1))
|
||||
for i in $(seq 0 $LAST_OUTDATED_INDEX); do
|
||||
OUTDATED_REVISION_ARN=$(echo "$TASK_REVISIONS" | jq -r ".taskDefinitionArns[$i]")
|
||||
|
||||
echo "Deregistering outdated task revision: $OUTDATED_REVISION_ARN"
|
||||
|
||||
$AWS_ECS deregister-task-definition --task-definition "$OUTDATED_REVISION_ARN" > /dev/null
|
||||
done
|
||||
fi
|
||||
|
||||
fi
|
||||
UPDATE_SERVICE_SUCCESS="true"
|
||||
break
|
||||
fi
|
||||
fi
|
||||
|
||||
sleep $every
|
||||
i=$(( $i + $every ))
|
||||
done
|
||||
|
||||
if [[ "${UPDATE_SERVICE_SUCCESS}" != "true" ]]; then
|
||||
# Timeout
|
||||
echo "ERROR: New task definition not running within $TIMEOUT seconds"
|
||||
if [[ "${ENABLE_ROLLBACK}" != "false" ]]; then
|
||||
rollback
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "Skipping check for running task definition, as desired-count <= 0"
|
||||
fi
|
||||
}
|
||||
|
||||
function waitForGreenDeployment {
|
||||
DEPLOYMENT_SUCCESS="false"
|
||||
every=2
|
||||
i=0
|
||||
echo "Waiting for service deployment to complete..."
|
||||
while [ $i -lt $TIMEOUT ]
|
||||
do
|
||||
NUM_DEPLOYMENTS=$($AWS_ECS describe-services --services $SERVICE --cluster $CLUSTER | jq "[.services[].deployments[]] | length")
|
||||
|
||||
# Wait until 1 deployment stays running
|
||||
# If the wait time has passed, we need to roll back
|
||||
if [ $NUM_DEPLOYMENTS -eq 1 ]; then
|
||||
echo "Service deployment successful."
|
||||
DEPLOYMENT_SUCCESS="true"
|
||||
# Exit the loop.
|
||||
i=$TIMEOUT
|
||||
else
|
||||
sleep $every
|
||||
i=$(( $i + $every ))
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ "${DEPLOYMENT_SUCCESS}" != "true" ]]; then
|
||||
if [[ "${ENABLE_ROLLBACK}" != "false" ]]; then
|
||||
rollback
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
function runTask {
|
||||
echo "Run task: $NEW_TASKDEF";
|
||||
AWS_ECS_RUN_TASK="$AWS_ECS run-task --cluster $CLUSTER --task-definition $NEW_TASKDEF"
|
||||
if [ $RUN_TASK_LAUNCH_TYPE != false ]; then
|
||||
AWS_ECS_RUN_TASK="$AWS_ECS_RUN_TASK --launch-type $RUN_TASK_LAUNCH_TYPE"
|
||||
fi
|
||||
|
||||
if [ $RUN_TASK_PLATFORM_VERSION != false ]; then
|
||||
AWS_ECS_RUN_TASK="$AWS_ECS_RUN_TASK --platform-version $RUN_TASK_PLATFORM_VERSION"
|
||||
fi
|
||||
|
||||
if [ $RUN_TASK_NETWORK_CONFIGURATION != false ]; then
|
||||
AWS_ECS_RUN_TASK="$AWS_ECS_RUN_TASK --network-configuration \"$RUN_TASK_NETWORK_CONFIGURATION\""
|
||||
fi
|
||||
|
||||
TASK_ARN=$(eval $AWS_ECS_RUN_TASK | jq -r '.tasks[0].taskArn')
|
||||
echo "Executed task: $TASK_ARN"
|
||||
|
||||
if [ $RUN_TASK_WAIT_FOR_SUCCESS == true ]; then
|
||||
RUN_TASK_SUCCESS=false
|
||||
every=10
|
||||
i=0
|
||||
while [ $i -lt $TIMEOUT ]
|
||||
do
|
||||
|
||||
TASK_JSON=$($AWS_ECS describe-tasks --cluster "$CLUSTER" --tasks "$TASK_ARN")
|
||||
|
||||
TASK_STATUS=$(echo $TASK_JSON | jq -r '.tasks[0].lastStatus')
|
||||
TASK_EXIT_CODE=$(echo $TASK_JSON | jq -r '.tasks[0].containers[0].exitCode')
|
||||
|
||||
if [ $TASK_STATUS == "STOPPED" ]; then
|
||||
echo "Task finished with status: $TASK_STATUS"
|
||||
if [ $TASK_EXIT_CODE != 0 ]; then
|
||||
echo "Task execution failed with exit code: $TASK_EXIT_CODE"
|
||||
exit 1
|
||||
fi
|
||||
RUN_TASK_SUCCESS=true
|
||||
break;
|
||||
fi
|
||||
|
||||
echo "Checking task status every $every seconds. Status: $TASK_STATUS"
|
||||
|
||||
sleep $every
|
||||
i=$(( $i + $every ))
|
||||
done
|
||||
|
||||
if [ $RUN_TASK_SUCCESS == false ]; then
|
||||
echo "ERROR: New task run took longer than $TIMEOUT seconds"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
|
||||
echo "Task $TASK_ARN executed successfully!"
|
||||
exit 0
|
||||
|
||||
}
|
||||
|
||||
######################################################
|
||||
# When not being tested, run application as expected #
|
||||
######################################################
|
||||
if [ "$BASH_SOURCE" == "$0" ]; then
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
set -u
|
||||
set -e
|
||||
# If no args are provided, display usage information
|
||||
if [ $# == 0 ]; then usage; fi
|
||||
|
||||
# Check for AWS, AWS Command Line Interface
|
||||
require aws
|
||||
# Check for jq, Command-line JSON processor
|
||||
require jq
|
||||
|
||||
# Loop through arguments, two at a time for key and value
|
||||
while [[ $# -gt 0 ]]
|
||||
do
|
||||
key="$1"
|
||||
|
||||
case $key in
|
||||
-k|--aws-access-key)
|
||||
AWS_ACCESS_KEY_ID="$2"
|
||||
shift # past argument
|
||||
;;
|
||||
-s|--aws-secret-key)
|
||||
AWS_SECRET_ACCESS_KEY="$2"
|
||||
shift # past argument
|
||||
;;
|
||||
-r|--region)
|
||||
AWS_DEFAULT_REGION="$2"
|
||||
shift # past argument
|
||||
;;
|
||||
-p|--profile)
|
||||
AWS_PROFILE="$2"
|
||||
shift # past argument
|
||||
;;
|
||||
--aws-instance-profile)
|
||||
echo "--aws-instance-profile is not yet in use"
|
||||
AWS_IAM_ROLE=true
|
||||
;;
|
||||
-a|--aws-assume-role)
|
||||
AWS_ASSUME_ROLE="$2"
|
||||
shift
|
||||
;;
|
||||
-c|--cluster)
|
||||
CLUSTER="$2"
|
||||
shift # past argument
|
||||
;;
|
||||
-n|--service-name)
|
||||
SERVICE="$2"
|
||||
shift # past argument
|
||||
;;
|
||||
-d|--task-definition)
|
||||
TASK_DEFINITION="$2"
|
||||
shift
|
||||
;;
|
||||
-i|--image)
|
||||
IMAGE="$2"
|
||||
shift
|
||||
;;
|
||||
-t|--timeout)
|
||||
TIMEOUT="$2"
|
||||
shift
|
||||
;;
|
||||
-m|--min)
|
||||
MIN="$2"
|
||||
shift
|
||||
;;
|
||||
-M|--max)
|
||||
MAX="$2"
|
||||
shift
|
||||
;;
|
||||
-D|--desired-count)
|
||||
DESIRED="$2"
|
||||
shift
|
||||
;;
|
||||
-e|--tag-env-var)
|
||||
TAGVAR="$2"
|
||||
shift
|
||||
;;
|
||||
-to|--tag-only)
|
||||
TAGONLY="$2"
|
||||
shift
|
||||
;;
|
||||
--max-definitions)
|
||||
MAX_DEFINITIONS="$2"
|
||||
shift
|
||||
;;
|
||||
--task-definition-file)
|
||||
TASK_DEFINITION_FILE="$2"
|
||||
shift
|
||||
;;
|
||||
--enable-rollback)
|
||||
ENABLE_ROLLBACK=true
|
||||
;;
|
||||
--use-latest-task-def)
|
||||
USE_MOST_RECENT_TASK_DEFINITION=true
|
||||
;;
|
||||
--force-new-deployment)
|
||||
FORCE_NEW_DEPLOYMENT=true
|
||||
;;
|
||||
--skip-deployments-check)
|
||||
SKIP_DEPLOYMENTS_CHECK=true
|
||||
;;
|
||||
--run-task)
|
||||
RUN_TASK=true
|
||||
;;
|
||||
--launch-type)
|
||||
RUN_TASK_LAUNCH_TYPE="$2"
|
||||
shift
|
||||
;;
|
||||
--platform-version)
|
||||
RUN_TASK_PLATFORM_VERSION="$2"
|
||||
shift
|
||||
;;
|
||||
--wait-for-success)
|
||||
RUN_TASK_WAIT_FOR_SUCCESS=true
|
||||
;;
|
||||
--network-configuration)
|
||||
RUN_TASK_NETWORK_CONFIGURATION="$2"
|
||||
shift
|
||||
;;
|
||||
--copy-task-definition-tags)
|
||||
COPY_TASK_DEFINITION_TAGS=true
|
||||
;;
|
||||
-v|--verbose)
|
||||
VERBOSE=true
|
||||
;;
|
||||
--version)
|
||||
echo ${VERSION}
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
#If another key was given that is not empty display usage.
|
||||
if [[ ! -z "$key" ]]; then
|
||||
usage
|
||||
exit 2
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
shift # past argument or value
|
||||
done
|
||||
|
||||
if [ $VERBOSE == true ]; then
|
||||
set -x
|
||||
fi
|
||||
|
||||
# Check that required arguments are provided
|
||||
assertRequiredArgumentsSet
|
||||
|
||||
if [[ "$AWS_ASSUME_ROLE" != false ]]; then
|
||||
assumeRole
|
||||
fi
|
||||
|
||||
# Not required creation of new a task definition
|
||||
if [ $FORCE_NEW_DEPLOYMENT == true ]; then
|
||||
updateServiceForceNewDeployment
|
||||
if [[ $SKIP_DEPLOYMENTS_CHECK != true ]]; then
|
||||
waitForGreenDeployment
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Determine image name
|
||||
parseImageName
|
||||
echo "Using image name: $useImage"
|
||||
|
||||
# Get current task definition
|
||||
getCurrentTaskDefinition
|
||||
echo "Current task definition: $TASK_DEFINITION_ARN";
|
||||
|
||||
# create new task definition json
|
||||
createNewTaskDefJson
|
||||
|
||||
# register new task definition
|
||||
registerNewTaskDefinition
|
||||
echo "New task definition: $NEW_TASKDEF";
|
||||
|
||||
# update service if needed
|
||||
if [ $SERVICE == false ]; then
|
||||
if [ $RUN_TASK == true ]; then
|
||||
runTask
|
||||
fi
|
||||
echo "Task definition updated successfully"
|
||||
else
|
||||
updateService
|
||||
|
||||
if [[ $SKIP_DEPLOYMENTS_CHECK != true ]]; then
|
||||
waitForGreenDeployment
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$AWS_ASSUME_ROLE" != false ]]; then
|
||||
assumeRoleClean
|
||||
fi
|
||||
|
||||
exit 0
|
||||
|
||||
fi
|
||||
#############################
|
||||
# End application run logic #
|
||||
#############################
|
||||
5
bin/git-drop-file-mode-changes.sh
Executable file
5
bin/git-drop-file-mode-changes.sh
Executable file
|
|
@ -0,0 +1,5 @@
|
|||
#/bin/sh
|
||||
|
||||
git diff -p -R --no-ext-diff --no-color \
|
||||
| grep -E "^(diff|(old|new) mode)" --color=never \
|
||||
| git apply;
|
||||
Loading…
Add table
Add a link
Reference in a new issue