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

Автор: | 01/02/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

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

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

[simterm]

$ ./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

[/simterm]

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

[simterm]

$ ./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.

[/simterm]

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

[simterm]

$ ./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.

[/simterm]

Готово.