Last active
October 26, 2023 00:39
-
-
Save anniethiessen/f73a3c65e9810b5ee9161e603c5c7be9 to your computer and use it in GitHub Desktop.
Script file to package and deploy AWS CloudFormation stacks.
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
| #!/usr/bin/env bash | |
| : ' | |
| Script file to package and deploy AWS CloudFormation stacks. | |
| Ensure AWS CLI is installed and configured, ensure STOML is installed, | |
| define script variables and configuration file, then execute script. | |
| Accepts -v (verbose output) and -q (quiet output) arguments. | |
| Prerequisites: | |
| - aws-cli 1.29.62 -> https://pypi.org/project/awscli/ | |
| - stoml 0.7.1 -> https://github.com/freshautomations/stoml | |
| - Install Go~=1.16 -> https://go.dev | |
| - Install stoml -> % go install github.com/freshautomations/[email protected] | |
| - Define stoml path script variable, if not ~/go/bin/stoml | |
| Configuration File: | |
| The configuration file replaces aws-cli command options with pre-defined env-specific parameters. | |
| Configuration file format should be in TOML or INI format. | |
| Section headers should be in format [<env>.<command>.parameters]. | |
| Global sections are retrieved as a last resort. | |
| Parameters are specified as key-value pairs, with the key | |
| being the aws-cli command option name -- replacing hyphens with underscores (e.g. --template-file -> template_file). | |
| See aws-cli CloudFormation docs for valid command parameters (command options). | |
| Only "true" boolean parameters are supported (e.g. disable_rollback = false will be ignored so use no_disable_rollback = true) | |
| Some parameters may cause conflicts: | |
| - no_execute_change_set: already set by script if ""CONFIRM_CHANGE_SET"" is set to "true" | |
| - change_set_name: should only be set if ""PERFORM_DEPLOY"" is set to "false", | |
| and ""PERFORM_DESCRIBE_CHANGE_SET"" and/or ""PERFORM_EXECUTE_CHANGE_SET"" is set to "true". | |
| This is because the ""deploy"" function creates a new change-set and passes | |
| the change-set name to the ""describe change-set"" and ""execute change-set"" functions. | |
| - no_paginate/max_items/starting_token: pagination is not supported by this script | |
| Script Variables: | |
| - CONDA_ENV: The conda environement that has required packages installed. | |
| Optional, if current environment has them installed. | |
| - STOML_PATH: Path to ""stoml"" go package. Do not surround with quotes. | |
| Optional, defaults to ~/go/bin/stoml. | |
| - CONFIG_FILE: Path and name of AWS CloudFormation configuration file. | |
| Optional, defaults to "config.toml". | |
| - CONFIG_ENV: Environment to use in the AWS configuration file. | |
| Optional, defaults to "default". | |
| - ARCHIVE_S3_BUCKET: S3 bucket to which archive files will be uploaded. | |
| The ""check"" function checks if it exists and provides an option to create it if necessary. | |
| Required, no default. | |
| - ARCHIVE_S3_BUCKET_REGION: AWS region of ""ARCHIVE_S3_BUCKET"", if created. | |
| Optional, defaults to "us-west-2". | |
| - ARCHIVE_S3_BUCKET_TAGS: List of tags to add to ""ARCHIVE_S3_BUCKET"", if created. | |
| Optional, defaults to (). | |
| - PERFORM_CHECK: Whether to perform the ""check"" step. | |
| The ""check"" function checks if required pre-existing resources exist. | |
| Currently, only ""ARCHIVE_S3_BUCKET"". | |
| Optional, defaults to "true". | |
| - PERFORM_PACKAGE: Whether to perform the ""package"" step. | |
| The ""package"" function packages local artifacts that the AWS CloudFormation template references | |
| to S3 and creates a clean output copy of the template, to be used by the ""deploy"" step. | |
| Parameter values for "package" function should be defined in the ""PACKAGE_PARAM_SECTION"" or ""GLOBAL_PARAM_SECTION"" sections of the ""CONFIG_FILE"". | |
| Should only be set to "false" if ""PERFORM_DEPLOY"" is also set to "false" | |
| or if a clean template for ""deploy"" step already exists. | |
| Optional, defaults to "true". | |
| - PERFORM_DEPLOY: Whether to perform the ""deploy"" step. | |
| The ""deploy"" function deploys specified template by creating, then executing a change-set. | |
| Parameter values for "package" function should be defined in the ""DEPLOY_PARAM_SECTION"" or ""GLOBAL_PARAM_SECTION"" sections of the ""CONFIG_FILE"". | |
| If ""CONFIRM_CHANGE_SET"" is set to "true", the change-set is displayed first, with an option to cancel deployment. | |
| Optional, defaults to "true". | |
| - CONFIRM_CHANGE_SET: Whether to confirm deploy change-set before executing it. | |
| Ignored if ""PERFORM_DEPLOY"" is set to "false". | |
| If set to "false", the ""deploy"" function deploys without displaying change-set. | |
| Optional, defaults to "true". | |
| - PERFORM_DESCRIBE_CHANGE_SET: Whether to perform the ""describe change-set"" sub-step independently. | |
| The ""describe change-set"" sub-step is part of the ""deploy"" step if ""CONFIRM_CHANGE_SET"" is set to "true". | |
| Parameter values for "package" function should be defined in the ""DESCRIBE_CHANGE_SET_PARAM_SECTION"" | |
| or ""DEPLOY_PARAM_SECTION"" or ""GLOBAL_PARAM_SECTION"" sections of the ""CONFIG_FILE"". | |
| Should only be set to "true" if ""PERFORM_DEPLOY"" is set to "false" | |
| because the ""deploy"" step already runs this sub-step after creating a change-set. | |
| If "true", the change-set must already exist and "change_set_name" must be defined in either the | |
| "CONFIG_ENV.describe_change_set.parameters", "CONFIG_ENV.deploy.parameters", or "CONFIG_ENV.global.parameters" | |
| section of ""CONFIG_FILE"". | |
| Optional, defaults to "false". | |
| - PERFORM_EXECUTE_CHANGE_SET: Whether to perform the ""execute change-set"" sub-step independently. | |
| The ""execute change-set"" sub-step is part of the ""deploy"" step. | |
| Parameter values for "package" function should be defined in the ""EXECUTE_CHANGE_SET_PARAM_SECTION"" | |
| or ""DEPLOY_PARAM_SECTION"" or ""GLOBAL_PARAM_SECTION"" sections of the ""CONFIG_FILE"". | |
| Should only be set to "true" if ""PERFORM_DEPLOY"" is set to "false" | |
| because the ""deploy"" step already runs this sub-step after creating a change-set. | |
| If "true", the change-set must already exist and "change_set_name" must be defined in either the | |
| "CONFIG_ENV.describe_change_set.parameters", "CONFIG_ENV.deploy.parameters", or "CONFIG_ENV.global.parameters" | |
| section of ""CONFIG_FILE"". | |
| Optional, defaults to "false". | |
| Usage Example: | |
| CONDA_ENV=xxx | |
| ARCHIVE_S3_BUCKET=xxx | |
| wget -cO - "<this_file_url>" > "temp.sh" | |
| chmod +x "temp.sh" | |
| source "temp.sh" "$@" | |
| rm -rf "temp.sh" | |
| ' | |
| #-------------------------------------------- | |
| #----------------- CONSTANTS ---------------- | |
| #-------------------------------------------- | |
| CONDA_ENV="${CONDA_ENV}" | |
| STOML_PATH=${STOML_PATH:-~/go/bin/stoml} | |
| CONFIG_FILE="${CONFIG_FILE:-config.toml}" | |
| CONFIG_ENV="${CONFIG_ENV:-default}" | |
| ARCHIVE_S3_BUCKET="${ARCHIVE_S3_BUCKET}" | |
| ARCHIVE_S3_BUCKET_REGION="${ARCHIVE_S3_BUCKET_REGION:-us-west-2}" | |
| ARCHIVE_S3_BUCKET_TAGS=${ARCHIVE_S3_BUCKET_TAGS:-()} | |
| PERFORM_CHECK=${PERFORM_CHECK:-true} | |
| PERFORM_PACKAGE=${PERFORM_PACKAGE:-true} | |
| PERFORM_DEPLOY=${PERFORM_DEPLOY:-true} | |
| CONFIRM_CHANGE_SET=${CONFIRM_CHANGE_SET:-true} | |
| PERFORM_DESCRIBE_CHANGE_SET=${PERFORM_DESCRIBE_CHANGE_SET:-false} | |
| PERFORM_EXECUTE_CHANGE_SET=${PERFORM_EXECUTE_CHANGE_SET:-false} | |
| #------- DO NOT EDIT BELOW THIS LINE -------- | |
| FORMAT_SCRIPT_URL="https://gist.githubusercontent.com/anniethiessen/efb6bc0e52ccfc8b330aa41364b53e97/raw/0012edc1f009a36d196f03f09fda68e70691860b/shell_script_essentials.sh" | |
| FORMAT_SCRIPT_NAME="shell_script_essentials.sh" | |
| GLOBAL_ENV_PRIMARY_CONFIG_SECTION="global" | |
| GLOBAL_COMMAND_SECONDARY_CONFIG_SECTION="global" | |
| PACKAGE_COMMAND_SECONDARY_CONFIG_SECTION="package" | |
| DEPLOY_COMMAND_SECONDARY_CONFIG_SECTION="deploy" | |
| DESCRIBE_CHANGE_SET_COMMAND_SECONDARY_CONFIG_SECTION="describe_change_set" | |
| EXECUTE_CHANGE_SET_COMMAND_SECONDARY_CONFIG_SECTION="execute_change_set" | |
| GLOBAL_TERTIARY_CONFIG_SECTION="global" | |
| PARAMETER_TERTIARY_CONFIG_SECTION="parameters" | |
| VALID_GLOBAL_COMMAND_PARAMS=("debug" "endpoint_url" "no_verify_ssl" "no_paginate" "output" "query" "profile" "region" "version" "color" "no_sign_request" "ca_bundle" "cli_read_timeout" "cli_connect_timeout") | |
| VALID_PACKAGE_COMMAND_PARAMS=("template_file" "s3_bucket" "s3_prefix" "kms_key_id" "output_template_file" "use_json" "force_upload" "metadata") | |
| VALID_DEPLOY_COMMAND_PARAMS=("template_file" "stack_name" "s3_bucket" "force_upload" "s3_prefix" "kms_key_id" "parameter_overrides" "capabilities" "no_execute_changeset" "disable_rollback" "no_disable_rollback" "role_arn" "notification_arns" "fail_on_empty_changeset" "no_fail_on_empty_changeset" "tags") | |
| VALID_DESCRIBE_CHANGE_SET_COMMAND_PARAMS=("change_set_name" "stack_name" "cli_input_json" "starting_token" "max_items" "generate_cli_skeleton") | |
| VALID_EXECUTE_CHANGE_SET_COMMAND_PARAMS=("change_set_name" "stack_name" "client_request_token" "disable_rollback" "no_disable_rollback" "retain_except_on_create" "no_retain_except_on_create" "cli_input_json" "generate_cli_skeleton") | |
| BOOLEAN_PARAMS=("debug" "no_verify_ssl" "no_paginate" "no_sign_request" "use_json" "force_upload" "fail_on_empty_changeset" "no_fail_on_empty_changeset" "disable_rollback" "no_disable_rollback" "no_execute_changeset" "retain_except_on_create" "no_retain_except_on_create") | |
| #-------------------------------------------- | |
| #--------------- FUNCTIONS ----------------- | |
| #-------------------------------------------- | |
| function run_format_script { | |
| wget -cO - ${FORMAT_SCRIPT_URL} > ${FORMAT_SCRIPT_NAME} | |
| chmod +x ${FORMAT_SCRIPT_NAME} | |
| source ${FORMAT_SCRIPT_NAME} "$@" | |
| rm -rf ${FORMAT_SCRIPT_NAME} | |
| } | |
| function get_aws_opts_from_config_file { | |
| local opts param value primary_config_section secondary_config_section tertiary_config_section flag | |
| local -n params=$1 | |
| local -n primary_config_sections=$2 | |
| local -n secondary_config_sections=$3 | |
| local -n tertiary_config_sections=$4 | |
| opts="" | |
| for param in "${params[@]}"; do | |
| value="" | |
| for primary_config_section in "${primary_config_sections[@]}"; do | |
| for secondary_config_section in "${secondary_config_sections[@]}"; do | |
| for tertiary_config_section in "${tertiary_config_sections[@]}"; do | |
| if [[ -z ${value} ]]; then | |
| value=$( ${STOML_PATH} "${CONFIG_FILE}" "${primary_config_section}.${secondary_config_section}.${tertiary_config_section}.${param}" ) | |
| fi | |
| done | |
| done | |
| done | |
| if [[ -n ${value} ]]; then | |
| flag=$( echo "--${param}" | sed "s/_/-/g" ) | |
| if [[ "${BOOLEAN_PARAMS[*]}" =~ (" "|^)${param}(" "|$) ]]; then | |
| if [[ ${value} == "true" ]]; then opts+=" ${flag}"; fi | |
| else | |
| opts+=" ${flag} ${value}" | |
| fi | |
| fi | |
| done | |
| echo "${opts}" | |
| } | |
| function generate_s3_bucket_tags { | |
| local tag_set tag tag_key tag_value tag_dict | |
| tag_set="" | |
| for tag in "${ARCHIVE_S3_BUCKET_TAGS[@]}" ; do | |
| tag_key="${tag%%:*}" | |
| tag_value="${tag##*:}" | |
| tag_dict="{Key=${tag_key},Value=${tag_value}}" | |
| tag_set="${tag_set}${tag_set:+,}${tag_dict}" | |
| done | |
| tag_set="[${tag_set}]" | |
| echo "${tag_set}" | |
| } | |
| function check_s3_bucket { | |
| local retval response | |
| aws s3api head-bucket \ | |
| --bucket "${ARCHIVE_S3_BUCKET}" \ | |
| &> ${OUTPUT} | |
| retval=$? | |
| if [[ ${retval} -eq 0 ]]; then | |
| output_success_message "S3 bucket ${ARCHIVE_S3_BUCKET} exists." | |
| else | |
| output_error_message "S3 bucket ${ARCHIVE_S3_BUCKET} does not exist." | |
| output_warning_message "Do you want to create S3 bucket ${S3_BUCKET}?" | |
| select response in "Yes" "No"; do | |
| case ${response} in | |
| Yes ) create_s3_bucket; break;; | |
| No ) exit_script;; | |
| esac | |
| done | |
| fi | |
| } | |
| function create_s3_bucket { | |
| local retval tag_set | |
| aws s3 mb s3://"${ARCHIVE_S3_BUCKET}" \ | |
| --region "${ARCHIVE_S3_BUCKET_REGION}" \ | |
| &> ${OUTPUT} | |
| retval=$? | |
| if [[ ${retval} -eq 0 ]]; then | |
| output_success_message "S3 bucket ${ARCHIVE_S3_BUCKET} created." | |
| else | |
| output_error_message "S3 bucket ${ARCHIVE_S3_BUCKET} creation error." ${PROMPT_VERBOSE} | |
| exit_script | |
| fi | |
| tag_set=$(generate_s3_bucket_tags) | |
| aws s3api put-bucket-tagging \ | |
| --bucket "${ARCHIVE_S3_BUCKET}" \ | |
| --tagging "TagSet=${tag_set}" \ | |
| &> ${OUTPUT} | |
| retval=$? | |
| if [[ ${retval} -eq 0 ]]; then | |
| output_success_message "S3 bucket tag set ${tag_set} added." | |
| else | |
| output_error_message "S3 bucket tag set ${tag_set} add error." ${PROMPT_VERBOSE} | |
| exit_script | |
| fi | |
| } | |
| function check { | |
| check_s3_bucket | |
| } | |
| function package { | |
| local params primary_config_sections secondary_config_sections tertiary_config_sections opts retval | |
| params=(`echo "${VALID_PACKAGE_COMMAND_PARAMS[@]}"` `echo "${VALID_GLOBAL_COMMAND_PARAMS[@]}"`) | |
| primary_config_sections=("${CONFIG_ENV}" "${GLOBAL_ENV_PRIMARY_CONFIG_SECTION}") | |
| secondary_config_sections=("${PACKAGE_COMMAND_SECONDARY_CONFIG_SECTION}" "${GLOBAL_COMMAND_SECONDARY_CONFIG_SECTION}") | |
| tertiary_config_sections=("${PARAMETER_TERTIARY_CONFIG_SECTION}" "${GLOBAL_TERTIARY_CONFIG_SECTION}") | |
| opts=$( get_aws_opts_from_config_file "${params}" "${primary_config_sections}" "${secondary_config_sections}" "${tertiary_config_sections}" ) | |
| opts+=" --no-paginate" | |
| output_info_message "Running 'package' command with options:" | |
| output_info_message "${opts}" | |
| aws cloudformation package ${opts} &> ${OUTPUT} | |
| retval=$? | |
| if [[ ${retval} -eq 0 ]]; then | |
| output_success_message "Stack packaged." | |
| else | |
| output_error_message "Stack packaging error." ${PROMPT_VERBOSE} | |
| exit_script | |
| fi | |
| } | |
| function describe_change_set { | |
| local params primary_config_sections secondary_config_sections tertiary_config_sections opts change_set_name ret retval | |
| params=(`echo "${VALID_DESCRIBE_CHANGE_SET_COMMAND_PARAMS[@]}"` `echo "${VALID_GLOBAL_COMMAND_PARAMS[@]}"`) | |
| primary_config_sections=("${CONFIG_ENV}" "${GLOBAL_ENV_PRIMARY_CONFIG_SECTION}") | |
| secondary_config_sections=("${DESCRIBE_CHANGE_SET_COMMAND_SECONDARY_CONFIG_SECTION}" "${DEPLOY_COMMAND_SECONDARY_CONFIG_SECTION}" "${GLOBAL_COMMAND_SECONDARY_CONFIG_SECTION}") | |
| tertiary_config_sections=("${PARAMETER_TERTIARY_CONFIG_SECTION}" "${GLOBAL_TERTIARY_CONFIG_SECTION}") | |
| opts=$( get_aws_opts_from_config_file "${params}" "${primary_config_sections}" "${secondary_config_sections}" "${tertiary_config_sections}" ) | |
| opts+=" --no-paginate" | |
| change_set_name=$1 | |
| if [[ -n ${change_set_name} ]]; then opts+=" --change-set-name ${change_set_name}"; fi | |
| output_info_message "Running 'describe-change-set' command with options:" | |
| output_info_message "${opts}" | |
| ret=$( aws cloudformation describe-change-set ${opts} 2>&1 ) | |
| echo "${ret}" | |
| retval=$? | |
| if [[ ${retval} -eq 0 ]]; then | |
| output_info_message "Stack change-set described." | |
| else | |
| output_error_message "Stack change-set description error." ${PROMPT_VERBOSE} | |
| exit_script | |
| fi | |
| } | |
| function execute_change_set { | |
| local params primary_config_sections secondary_config_sections tertiary_config_sections opts change_set_name retval | |
| params=(`echo "${VALID_EXECUTE_CHANGE_SET_COMMAND_PARAMS[@]}"` `echo "${VALID_GLOBAL_COMMAND_PARAMS[@]}"`) | |
| primary_config_sections=("${CONFIG_ENV}" "${GLOBAL_ENV_PRIMARY_CONFIG_SECTION}") | |
| secondary_config_sections=("${EXECUTE_CHANGE_SET_COMMAND_SECONDARY_CONFIG_SECTION}" "${DEPLOY_COMMAND_SECONDARY_CONFIG_SECTION}" "${GLOBAL_COMMAND_SECONDARY_CONFIG_SECTION}") | |
| tertiary_config_sections=("${PARAMETER_TERTIARY_CONFIG_SECTION}" "${GLOBAL_TERTIARY_CONFIG_SECTION}") | |
| opts=$( get_aws_opts_from_config_file "${params}" "${primary_config_sections}" "${secondary_config_sections}" "${tertiary_config_sections}" ) | |
| opts+=" --no-paginate" | |
| change_set_name=$1 | |
| if [[ -n ${change_set_name} ]]; then opts+=" --change-set-name ${change_set_name}"; fi | |
| output_info_message "Running 'execute-change-set' command with options:" | |
| output_info_message "${opts}" | |
| aws cloudformation execute-change-set ${opts} &> ${OUTPUT} | |
| retval=$? | |
| if [[ ${retval} -eq 0 ]]; then | |
| output_info_message "Stack change-set executed." | |
| else | |
| output_error_message "Stack change-set execution error." ${PROMPT_VERBOSE} | |
| exit_script | |
| fi | |
| } | |
| function deploy { | |
| local params primary_config_sections secondary_config_sections tertiary_config_sections opts ret retval change_set_name stack_name response | |
| params=(`echo "${VALID_DEPLOY_COMMAND_PARAMS[@]}"` `echo "${VALID_GLOBAL_COMMAND_PARAMS[@]}"`) | |
| primary_config_sections=("${CONFIG_ENV}" "${GLOBAL_ENV_PRIMARY_CONFIG_SECTION}") | |
| secondary_config_sections=("${DEPLOY_COMMAND_SECONDARY_CONFIG_SECTION}" "${GLOBAL_COMMAND_SECONDARY_CONFIG_SECTION}") | |
| tertiary_config_sections=("${PARAMETER_TERTIARY_CONFIG_SECTION}" "${GLOBAL_TERTIARY_CONFIG_SECTION}") | |
| opts=$( get_aws_opts_from_config_file "${params}" "${primary_config_sections}" "${secondary_config_sections}" "${tertiary_config_sections}" ) | |
| opts+=" --no-paginate" | |
| if [[ "${CONFIRM_CHANGE_SET}" == "true" ]]; then | |
| opts+=" --no-execute-changeset" | |
| output_info_message "Running 'deploy' command with options:" | |
| output_info_message "${opts}" | |
| ret=$( aws cloudformation deploy ${opts} 2>&1 ) | |
| if [[ "${OUTPUT}" == "${VERBOSE_OUTPUT}" ]]; then echo "${ret}"; fi | |
| change_set_name=$( awk -F"--change-set-name " '{print $2}' <<< "${ret}" ) | |
| change_set_name=$( echo "${change_set_name##*$'\n'}" ) | |
| change_set_name=$( sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' <<< "${change_set_name}" ) | |
| if [[ -z ${change_set_name} ]]; then | |
| stack_name="${opts#*--stack-name }" | |
| stack_name="${stack_name%% --*}" | |
| no_change_ret=$( awk -F"No changes to deploy. " '{print $2}' <<< "${ret}" ) | |
| no_change_ret=$( echo "${no_change_ret##*$'\n'}" ) | |
| no_change_ret=$( sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' <<< "${no_change_ret}" ) | |
| if [[ "${no_change_ret}" == "Stack ${stack_name} is up to date" ]]; then | |
| output_info_message "No stack change-set to display." | |
| exit_script 0 | |
| else | |
| output_error_message "Stack change-set creation error." ${PROMPT_VERBOSE} | |
| exit_script | |
| fi | |
| else | |
| output_info_message "Stack change-set created." | |
| describe_change_set "${change_set_name}" | |
| output_question_message "Do you want to execute stack change-set ${change_set_name}?" | |
| select response in "Yes" "No"; do | |
| case ${response} in | |
| Yes ) output_info_message "Executing stack change-set."; execute_change_set "${change_set_name}"; break;; | |
| No ) output_info_message "Not executing stack change-set."; exit_script 0;; | |
| esac | |
| done | |
| retval=$? | |
| if [[ ${retval} -eq 0 ]]; then | |
| output_success_message "Stack deployed." | |
| else | |
| output_error_message "Stack deployment error." ${PROMPT_VERBOSE} | |
| exit_script | |
| fi | |
| fi | |
| else | |
| output_info_message "Running 'deploy' command with options:" | |
| output_info_message "${opts}" | |
| ret=$( aws cloudformation deploy ${opts} 2>&1 ) | |
| if [[ "${OUTPUT}" == "${VERBOSE_OUTPUT}" ]]; then echo "${ret}"; fi | |
| stack_name="${opts#*--stack-name }" | |
| stack_name="${stack_name%% --*}" | |
| no_change_ret=$( awk -F"No changes to deploy. " '{print $2}' <<< "${ret}" ) | |
| no_change_ret=$( echo "${no_change_ret##*$'\n'}" ) | |
| no_change_ret=$( sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' <<< "${no_change_ret}" ) | |
| if [[ "${no_change_ret}" == "Stack ${stack_name} is up to date" ]]; then | |
| output_info_message "No stack change-set to deploy." | |
| exit_script 0 | |
| fi | |
| success_ret=$( awk -F"Successfully " '{print $2}' <<< "${ret}" ) | |
| success_ret=$( echo "${success_ret##*$'\n'}" ) | |
| success_ret=$( sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' <<< "${success_ret}" ) | |
| if [[ "${success_ret}" != "created/updated stack - ${stack_name}" ]]; then | |
| output_error_message "Stack deployment error." ${PROMPT_VERBOSE} | |
| exit_script | |
| else | |
| output_success_message "Stack deployed." | |
| fi | |
| fi | |
| } | |
| #-------------------------------------------- | |
| #------------------ MAIN -------------------- | |
| #-------------------------------------------- | |
| run_format_script "$@" | |
| if [ -n "${CONDA_ENV}" ]; then | |
| eval "$(conda shell.bash hook)" | |
| conda activate ${CONDA_ENV} | |
| fi | |
| if [[ "${OUTPUT}" == "${VERBOSE_OUTPUT}" ]]; then | |
| PYTHON_VERSION=$( python --version 2>&1 ) | |
| AWSCLI_VERSION=$( aws --version 2>&1 ) | |
| output_warning_message "Using ${PYTHON_VERSION} and ${AWSCLI_VERSION}" | |
| fi | |
| output_header_message "----------------------------------------" | |
| output_header_message "[1/3] CHECK" | |
| output_header_message "checking required resources exist ..." | |
| output_header_message "----------------------------------------" | |
| if [ "${PERFORM_CHECK}" == true ] ; then | |
| check | |
| else output_warning_message "Checks skipped"; fi | |
| output_header_message "----------------------------------------" | |
| output_header_message "[2/3] PACKAGE" | |
| output_header_message "packaging and uploading archive to S3 ..." | |
| output_header_message "----------------------------------------" | |
| if [ "${PERFORM_PACKAGE}" == true ] ; then | |
| package | |
| else output_warning_message "Package skipped"; fi | |
| output_header_message "----------------------------------------" | |
| output_header_message "[3/3] DEPLOY" | |
| output_header_message "deploying stack to CloudFormation ..." | |
| output_header_message "----------------------------------------" | |
| if [ "${PERFORM_DEPLOY}" == true ] ; then | |
| deploy | |
| else output_warning_message "Deploy skipped"; fi | |
| if [ "${PERFORM_DESCRIBE_CHANGE_SET}" == true ] ; then | |
| output_header_message "----------------------------------------" | |
| output_header_message "[3b/3] DESCRIBE CHANGE-SET" | |
| output_header_message "describing existing change-set ..." | |
| output_header_message "----------------------------------------" | |
| describe_change_set | |
| fi | |
| if [ "${PERFORM_EXECUTE_CHANGE_SET}" == true ] ; then | |
| output_header_message "----------------------------------------" | |
| output_header_message "[3c/3] EXECUTE CHANGE-SET" | |
| output_header_message "executing existing change-set ..." | |
| output_header_message "----------------------------------------" | |
| execute_change_set | |
| fi |
Author
Author
Raw URLs:
Author
TODO:
-add cloudformation validate step
Author
Change Log:
v1: Initial
v2:
-Added CONDA_ENV variable: Conda environment is activated if defined
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Known Issues:
v1:
-(#1) local: -n: invalid option errors, research shows its a bash<4.3 issue but still occurring on bash5.2
-(#2) awscli retvals are not totally dependable and some edge-case success/error messages may not be correct
v2: