Created
October 28, 2024 20:54
-
-
Save dazza-codes/b3da2aa541669cda5cf1179b06b96503 to your computer and use it in GitHub Desktop.
AWS Lambda Layer Publish Script
This file contains 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 | |
# Copyright 2020-2024 Darren Weber | |
# | |
# Licensed under the Apache License, Version 2.0 (the "License"). You may not | |
# use this file except in compliance with the License. A copy of the License is | |
# located at | |
# | |
# http://aws.amazon.com/apache2.0/ | |
# | |
# or in the "license" file accompanying this file. This file is distributed on | |
# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express | |
# or implied. See the License for the specific language governing permissions | |
# and limitations under the License. | |
SCRIPT_PATH=$(dirname "$0") | |
SCRIPT_PATH=$(readlink -f "$SCRIPT_PATH") | |
PY_VERSION=$(python --version | grep -o -E '[0-9]+[.][0-9]+') | |
LAMBDA_REGION=${AWS_DEFAULT_REGION:-'us-west-2'} | |
LAMBDA_ACCOUNT=${AWS_ACCOUNT} | |
LAMBDA_BUCKET=${LAMBDA_BUCKET:-'lambda-deploys'} | |
S3_PREFIX=${S3_PREFIX:-'lambda-layers'} | |
S3_ROOT=s3://${LAMBDA_BUCKET}/${S3_PREFIX} | |
crash () { | |
echo "OOPS - something went wrong!" | |
exit 1 | |
} | |
create_or_update_layer () { | |
zip_file=$1 | |
file_name=$(basename "$f") | |
layer_name=$(echo "${file_name}" | sed -e 's/.zip//' -e 's/\./-/g') | |
layer_arn="arn:aws:lambda:${LAMBDA_REGION}:${LAMBDA_ACCOUNT}:layer:${layer_name}" | |
echo | |
printf "CHECK LAYER VERSIONS %-40s -> %s\n" "${file_name}" "${layer_arn}" | |
# To be smarter at detecting whether an update is required or not | |
# - check some sha256 hashes and the zip archive file size | |
# - see also https://stackoverflow.com/questions/9714139/why-does-zipping-the-same-content-twice-gives-two-files-with-different-sha1 | |
# - use the right options on zip to get the same archive for the same content | |
ver_json='/tmp/layer_versions.json' | |
rm -f "${ver_json}" | |
aws lambda list-layer-versions \ | |
--layer-name "${layer_arn}" \ | |
--compatible-runtime "python${PY_VERSION}" \ | |
--no-paginate --output json > "${ver_json}" | |
if [ -f "${ver_json}" ] && [ -s "${ver_json}" ]; then | |
layer_ver_arn=$(jq '.LayerVersions | sort_by(.Version)[].LayerVersionArn' "${ver_json}" | tail -n1 | sed 's/"//g') | |
if [ "${layer_ver_arn}" != "" ]; then | |
printf "LATEST LAYER VERSION %-40s -> %s\n" "${file_name}" "${layer_ver_arn}" | |
aws lambda get-layer-version-by-arn --arn "${layer_ver_arn}" > "${ver_json}" | |
layer_hash=$(jq '.Content.CodeSha256' "${ver_json}" | tail -n1 | sed 's/"//g') | |
layer_size=$(jq '.Content.CodeSize' "${ver_json}" | tail -n1 | sed 's/"//g') | |
# https://stackoverflow.com/questions/33825815/how-to-calculate-the-codesha256-of-aws-lambda-deployment-package-before-uploadin | |
zip_size=$(stat --format '%s' "${zip_file}") | |
zip_hash=$(openssl dgst -sha256 -binary "${zip_file}" | openssl enc -base64) | |
echo -e "lambda size: ${layer_size}" | |
echo -e "zip file size: ${zip_size}" | |
echo -e "lambda sha256: ${layer_hash}" | |
echo -e "zip file sha256: ${zip_hash}" | |
[ "${zip_size}" == "${layer_size}" ] \ | |
&& [ "${zip_hash}" == "${layer_hash}" ] \ | |
&& echo -e "SKIP layer publication\n\n" \ | |
&& return | |
else | |
echo "There is no lambda layer published" | |
fi | |
else | |
echo "There is no lambda layer published" | |
fi | |
echo | |
printf "CREATE or UPDATE LAYER %-40s -> %s\n" "${file_name}" "${layer_arn}" | |
aws s3 ls "${S3_ROOT}/${file_name}" > /dev/null || crash | |
# shellcheck disable=SC2140 | |
aws lambda publish-layer-version \ | |
--region "${LAMBDA_REGION}" \ | |
--layer-name "${layer_arn}" \ | |
--description "${layer_name}" \ | |
--license-info "PRIVATE" \ | |
--content S3Bucket="${LAMBDA_BUCKET}",S3Key="${S3_PREFIX}/${file_name}" \ | |
--compatible-runtimes "python${PY_VERSION}" | |
echo | |
} | |
if ! command -v jq > /dev/null; then | |
curl -o jq-linux64 -sSL https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64 \ | |
&& mv jq-linux64 ${HOME}/bin/jq \ | |
&& chmod a+x ${HOME}/bin/jq \ | |
&& jq --version | |
fi | |
aws s3 sync "${SCRIPT_PATH}" "${S3_ROOT}"/ --exclude '*' --include '*.zip' | |
for f in "${SCRIPT_PATH}"/*.zip; do | |
zip_file=$(basename "$f") | |
create_or_update_layer "${zip_file}" | |
done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment