BASH: скрипт создания AWS CloudFormation стека

By | 02/01/2018
 

На одном из проектов создавался CloudFormation шаблон для RDS (см. пример тут>>>).

Что бы упростить создание и обновление стека разработчиками – набросал небольшой скрипт.

Скрипт выполняет:

  1. валидацию файла шаблона
  2. проверит требуется ли создать, или обновить стек
  3. запросит подтверждение перед созданием
  4. выполнит create-stack или update-stack

Чать параметров используется из файла шаблона или переменных скрипта, дефолтные, часть – обязательные.

В случае использования не-дефолтных значений – их надо указывать все.

Сам скрипт:

#!/usr/bin/env bash

HELP="\n\t1 arg: mandatory - AWS credentials profile (e.g. ads)\n\t\
2 arg: mandatory - stack name. Valid values: ads-rds-dev, ads-rds-production.).\n\t\
3 arg: optional - template file. Default - ads-rds-pg.json.\n\t\
4 arg: optional - DB instance type, valid values: db.t2.micro, db.m1.small, db.m1.large, db.m1.xlarge, db.m2.xlarge, db.m3.large. Default - db.t2.micro.\n\t\
5 arg: optional - storage size (in GB), valid values 5-6144. Default - 5 GB.\n\

Example:

./create_stack.sh ads ads-rds-dev db.m1.large 100
"

[[ $# -lt 2 ]] && { echo -e "$HELP"; exit 1; }

PROFILE=$1
STACK_NAME=$2
[[ $# -gt 2  ]] && TEMPLATE=$3 || TEMPLATE="../ads-rds-pg.json"
[[ $# -gt 3 ]] && DB_TYPE=$4 || DB_TYPE="db.t2.micro"
[[ $# -gt 4 ]] && DB_STORAGE_SIZE=$5 || DB_STORAGE_SIZE=5

# will contain "create" or "update" to chose action
CREATE_OR_UPDATE=

# link to CloudFormation stacks
CF_URL="https://us-west-1.console.aws.amazon.com/cloudformation/home?region=us-west-1#/stacks?filter=active&tab=events"

echo -e "\nStarting AWS CloudFormation stack creation using:\n
profile: $PROFILE
stack name: $STACK_NAME
template: $TEMPLATE
DB instance type: $DB_TYPE
DB storage size: $DB_STORAGE_SIZE"

# all functions

cf_template_validate () {

    local profile=$1
    local template=$2
    aws cloudformation --profile $profile validate-template --template-body file://$template
}

cf_stack_check_create_or_update () {

    local profile=$1
    aws cloudformation --profile $profile describe-stacks --query 'Stacks[*].StackName' --output text
}

cf_stack_exec_create_or_update () {

    local profile=$1
    local stack_name=$2
    local template=$3
    local db_type=$4
    local db_storage_size=$5
    local create_or_update=$6

    aws cloudformation --profile $profile $create_or_update-stack --stack-name $stack_name --template-body file://$template --parameters \
    ParameterKey=DBClass,ParameterValue=$db_type \
    ParameterKey=DBAllocatedStorage,ParameterValue=$db_storage_size
}

# execution starts here

echo -e "\nValidating template $TEMPLATE...\n"
if cf_template_validate $PROFILE $TEMPLATE; then
    echo -e "\nTemplate OK"
else
    echo -e "\nERROR: can not validate template, fix erros and try again. Exit.\n"
    exit 1
fi

echo -e "\nChecking if stack $STACK_NAME already present..."
if  [[ $(cf_stack_check_create_or_update $PROFILE) =~ $STACK_NAME ]]; then
    echo -e "\nStack $STACK_NAME found, preparing Stack Update.\n"
    CREATE_OR_UPDATE="update"
else
    echo -e "\nStack $STACK_NAME not found, running Stack Create.\n"
    CREATE_OR_UPDATE="create"
fi

read -p "Are you sure to proceed? [y/n] " -n 1 -r
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
    exit 1
fi

# this will execute command like:
# aws cloudformation --profile ads create-stack --stack-name ads-rds-dev --template-body file://ads-rds-pg.json --parameters ParameterKey=DBClass,ParameterValue=db.t2.micro ParameterKey=DBAllocatedStorage,ParameterValue=5

# see arguments list for the cf_stack_exec_create_or_update() function:
#
#    local profile=$1
#    local stack_name=$2
#    local template=$3
#    local db_type=$4
#    local db_storage_size=$5
#    local create_or_update=$6

echo -e "\n\nRunning create or update stack $STACK_NAME..."
if [[ $(cf_stack_exec_create_or_update $PROFILE $STACK_NAME $TEMPLATE $DB_TYPE $DB_STORAGE_SIZE $CREATE_OR_UPDATE) ]]; then
    echo -e "\nStack creation started. Use $CF_URL to check its status.\n"
else
    echo -e "\nSomething went wrong, use $CF_URL to check it for errors.\n"
fi

Примеры выполнения.

При вызове без параметров – выведет помощь по опциям:

./create_stack.sh
1 arg: mandatory - AWS credentials profile (e.g. ads)
2 arg: mandatory - stack name. Valid values: ads-rds-dev, ads-rds-production.).
3 arg: optional - template file. Default - ads-rds-pg.json.
4 arg: optional - DB instance type, valid values: db.t2.micro, db.m1.small, db.m1.large, db.m1.xlarge, db.m2.xlarge. Default - db.t2.micro.
5 arg: optional - storage size (in GB), valid values 5-6144. Default - 5 GB.
Example:
./create_sctak.sh ads ads-rds-dev db.m1.large 100

Для Dev окружения, с использованием значений по-умолчанию:

./create_stack.sh ads ads-rds-dev
Starting AWS CloudFormation stack creation using:
profile: ads
stack name: ads-rds-dev
template: ../ads-rds-pg.json
DB instance type: db.t2.micro
DB storage size: 5
Validating template ../ads-rds-pg.json...
{
"Parameters": [
{
"ParameterKey": "DBClass",
"DefaultValue": "db.t2.micro",
"NoEcho": false,
"Description": "Database instance class"
},
{
"ParameterKey": "DBPassword",
"DefaultValue": "password",
"NoEcho": true,
"Description": "The database admin account password"
},
{
"ParameterKey": "DBAllocatedStorage",
"DefaultValue": "5",
"NoEcho": false,
"Description": "The size of the database (Gb)"
},
{
"ParameterKey": "VPCCIDRBlock",
"DefaultValue": "10.0.0.0/16",
"NoEcho": false,
"Description": "VPC CIDR block"
},
{
"ParameterKey": "KievAllowLocation",
"DefaultValue": "77.***.***.20/32",
"NoEcho": false,
"Description": "The IP address range that can be used to access RDS instance"
},
{
"ParameterKey": "PublicSubnet1bCIDR",
"DefaultValue": "10.0.16.0/28",
"NoEcho": false,
"Description": "Public Subnet CIDR, zone B"
},
{
"ParameterKey": "TableauProdAllowIP",
"DefaultValue": "52.***.***.245/32",
"NoEcho": false,
"Description": "The IP address range that can be used to access RDS instance"
},
{
"ParameterKey": "PublicSubnet1aCIDR",
"DefaultValue": "10.0.1.0/28",
"NoEcho": false,
"Description": "Public Subnet CIDR, zone A"
},
{
"ParameterKey": "DBUsername",
"DefaultValue": "pgadminusername",
"NoEcho": true,
"Description": "The database admin account username"
}
],
"Description": "AWS CloudFormation stack for ADS RDS instance."
}
Template OK
Checking if stack ads-rds-dev already present...
Stack ads-rds-dev not found, running Stack Create.
Are you sure to proceed? [y/n] y
Running create or update stack ads-rds-dev...
Stack creation started. Use https://us-west-1.console.aws.amazon.com/cloudformation/home?region=us-west-1#/stacks?filter=active&tab=events to check its status.

Для Production, с переопределением типа RDS инстанса и размера диска под него:

./create_stack.sh ads ads-rds-production-test ../ads-rds-pg.json db.m3.large 100
Starting AWS CloudFormation stack creation using:
profile: ads
stack name: ads-rds-production-test
template: ../ads-rds-pg.json
DB instance type: db.m1.large
DB storage size: 100
Validating template ../ads-rds-pg.json...
{
"Parameters": [
...
"Description": "AWS CloudFormation stack for ADS RDS instance."
}
Template OK
Checking if stack ads-rds-production-test already present...
Stack ads-rds-production-test not found, running Stack Create.
Are you sure to proceed? [y/n] y
Running create or update stack ads-rds-production-test...
Stack creation started. Use https://us-west-1.console.aws.amazon.com/cloudformation/home?region=us-west-1#/stacks?filter=active&tab=events to check its status.

Готово.