Skip to content

Instantly share code, notes, and snippets.

@dazza-codes
Created October 28, 2024 20:54
Show Gist options
  • Save dazza-codes/b3da2aa541669cda5cf1179b06b96503 to your computer and use it in GitHub Desktop.
Save dazza-codes/b3da2aa541669cda5cf1179b06b96503 to your computer and use it in GitHub Desktop.
AWS Lambda Layer Publish Script
#!/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