Saturday 10 February 2018

Shell script to update lambda code and environment variables to multiple regions and environments using AWS CLI

Background

If you are using AWS stack in your project then you must have used Lambda service some or the other time. It is what we call the serverless architecture. You do not care about the hardware or the  operating system. You just provide the Lambda with the code you wish to run which can be triggered from multiple sources like an S3, API gateway etc.

Since AWS services are region specific you may have same lambda code running in multiple regions. You will have to go to each region and deploy your lambda code either by directly uploading the zip file or uploading from S3 bucket in same region. Either ways this way is time consuming and repetitive. Also you might have same code running under different names corresponding to different execution environments like dev,qa,production etc. Also each lambda may have environment variables like database configuration settings or other custom setting like memory and timeout.

In this post I will show you a simple shell script that uses AWS CLI to do this from your local machine. You can just run this command and it will take care of deploying your code, changing environment variables and setting custom configurations for each region you wish to deploy lambda to.




Assumptions and Setup

This deployment script assumes you have installed AWS Cli and configure a profile in it. If you have not done it already refer -
NOTE : If you are not explicitly providing a profile name to aws configure it is by default set as "default"

Next this script also assumes you have local zip file that has your lambda code. This script also takes an env variables as the input which expects your lambda function name to have it as a suffix. So if your base lambda function name is "my-lambda" then your actual lambda function name is different environments should be -
  • test : my-lambda-test
  • dev : my-lambda-dev
  • qa : my-lambda-qa
  • prod : my-lambda-prod
Script has the base name of the lambda and some environment variables that are defined globally and per region. Script also has array of regions the lambda should be updated to. These  things you can change as per your usecase.


Shell script code

You can find the code on my Github gist -
I am also adding it below to explain it how it works. However to see the most recent version refer to the gist link above.

Code is as follows -

#!/bin/bash
#----------------------------------------------------
#  Author : athakur
#  Version : 1.0
#  Date : 10/02/2018
#  Description : Deployment script to update lambda code and env variables
#  Sample usage :  
#    Local : ./update-lambda.sh test aws-admin fileb://../lambda.zip
#    Dev : ./update-lambda.sh dev aws-admin fileb://../lambda.zip
#    QA : ./update-lambda.sh qa aws-admin fileb://../lambda.zip
#    Prod : ./update-lambda.sh prod aws-admin fileb://../lambda.zip
#----------------------------------------------------
echo "Updating lambda code for ENV : $1 PROFILE : $2 ZIP_FILE_PATH : $3"

ENV=$1
PROFILE=$2
ZIP_FILE_PATH=$3

if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ]
  then
  echo "Incorrect arguments supplied. Format - ./update-lambda.sh ENV PROFILE ZIP_FILE_PATH"
  exit
fi

FUNCTION_NAME="my-lambda-$ENV"

ENV_VAR_1=1991
ENV_VAR_2="password"


SNS_ENDPOINT=''

SUPPORTED_REGIONS=("us-east-1" "ap-northeast-1" "ap-southeast-1" "ap-southeast-2")

for REGION in ${SUPPORTED_REGIONS[@]}
do
    echo 'Region : $REGION'
    case "$REGION" in
        "us-east-1")
            SNS_ENDPOINT="arn:aws:sns:us-east-1:123456789123:my-sns-notification"
        ;;
        "ap-northeast-1")
            SNS_ENDPOINT="arn:aws:sns:ap-northeast-1:123456789123:my-sns-notification"
        ;;
        "ap-southeast-1")
            SNS_ENDPOINT="arn:aws:sns:ap-southeast-1:123456789123:my-sns-notification"
        ;;
        "ap-southeast-2")
            SNS_ENDPOINT="arn:aws:sns:ap-southeast-2:123456789123:my-sns-notification"
        ;;                    
        *)
            echo "Environment not provided"
            exit 1
        ;;
    esac

    env_variables="{\"Variables\":{\"ENV_VAR_1\":\"${ENV_VAR_1}\",\"ENV_VAR_2\":\"${ENV_VAR_2}\",\"SNS_ENDPOINT\":\"${SNS_ENDPOINT}\",\"ENV\":\"${ENV}\"}}"
    echo "Env variables :  $env_variables"        
    lambda_update_env_command="aws lambda update-function-configuration --function-name $FUNCTION_NAME --region $REGION --profile $PROFILE --environment '$env_variables' --timeout 300 --memory-size 3008"    
    echo "Executing command : $lambda_update_env_command"
    eval $lambda_update_env_command
    lambda_update_code_command="aws lambda update-function-code --function-name $FUNCTION_NAME --region $REGION --zip-file $ZIP_FILE_PATH --profile $PROFILE"    
    echo "Executing command : $lambda_update_code_command"
    eval $lambda_update_code_command    
    echo "Completed Lambda function update for region $REGION"
done


Now let's try to understand what we are doing in above shell script.

Understanding the shell script

Above shell script takes 3 arguments -
  1. Env : This is the env. Eg. test, dev, qa, prod etc
  2. Profile name : This is the aws profile name configured. If you have not done so this will just be "default"
  3. zip file path : Path to lambda zip file

 First part of the script validates that you provided arguments needed for script to run. Next we define some environment variables that we need to set for our lambda. Next we set a environment variable called SNS_ENDPOINT that changes per region. You can do a similar code snippet per environment as well.

Next we have an array of aws regions we need to deploy our lambda code in. You can add / remove as per your use case. Finally we run 2 aws commands for each region -
  1. update-function-configuration : This updates the environment variables and other configurations needed by your lambda
  2. update-function-code : This updates the actual lambda code that gets deployed to the lamdba.
NOTE :  We are also setting --timeout 300 --memory-size 3008 which basically sets lambda timeout and memory to maximum available i.e 5 mins and 3 GB respectively.

NOTE :  Lambda is charged as the amount of time it runs * memory it uses. So change above configurations as per your need and budget.



Related Links


t> UA-39527780-1 back to top