293

I created a lambda function in AWS (Python) using "upload .zip" I lost those files and I need to make some changes, is there is any way to download that .zip?

Jedi
  • 3,088
  • 2
  • 28
  • 47
Elheni Mokhles
  • 3,801
  • 2
  • 12
  • 17

5 Answers5

520

Yes!

Navigate over to your lambda function settings and on the top right you will have a button called "Actions". In the drop down menu select "export" and in the popup click "Download deployment package" and the function will download in a .zip file.

Action button on top-right

Step#1

A popup from CTA above (Tap "Download deployment package" here)

Step#2

choz
  • 17,242
  • 4
  • 53
  • 73
Bubble Hacker
  • 6,425
  • 1
  • 17
  • 24
  • 2
    Click on the function. When you are in the functions management page click actions. – Bubble Hacker Dec 03 '17 at 07:51
  • 1
    @kit Yes! In the output of the command you should see `code` in there you should find `location`. This is a presigned URL that you can use to download the function. The URL will be valid for 10 minutes. – Bubble Hacker Dec 13 '17 at 13:00
  • @kit Did you find a way to download the zip using CLI? I have no luck with wget or even curl – Vineeth Feb 28 '18 at 12:50
  • 2
    @Vineeth- Yes you can make use of command like: AWS_ACCESS_KEY_ID=XXX AWS_SECRET_ACCESS_KEY=XXX aws s3 cp s3://my-images/dev . --recursive – ketan Feb 28 '18 at 13:53
  • 8
    Worked for me. Just a note that the file I downloaded did not have a `.zip` extension so was just a plain file in Windows. The solution is to manually add the extension to the file name after downloading. – The Unknown Dev Apr 22 '18 at 22:35
  • I don't have an "Export function" button. Perhaps because my function is a container image. Need to know how to download a container image function. – foobarbecue Apr 25 '23 at 23:17
47

Update: Added link to script by sambhaji-sawant. Fixed Typos, improved answer and script based on comments!

You can use aws-cli to download the zip of any lambda.

First you need to get the URL to the lambda zip $ aws lambda get-function --function-name $functionName --query 'Code.Location'

Then you need to use wget/curl to download the zip from the URL. $ wget -O myfunction.zip URL_from_step_1

Additionally you can list all functions on your AWS account using

$ aws lambda list-functions

I made a simple bash script to parallel download all the lambda functions from your AWS account. You can see it here :)

Note: You will need to setup aws-cli before using the above commands (or any aws-cli command) using aws configure

Full guide here

Arjun Nemani
  • 570
  • 4
  • 5
  • aws lambda get-function returns a JSON description of the function. To get the actual zip, you need to use the Code.Location attribute with curl or some other HTTP client. – jonseymour Mar 26 '19 at 06:22
  • New link is at the answer below: https://stackoverflow.com/a/55159281/2506135 – John Lee Mar 19 '21 at 23:56
  • This does not work, even though I am using a profile with credentials, it returns: Connecting to awslambda-us-west-2-tasks.s3.us-west-2.amazonaws.com (awslambda-us-west-2-tasks.s3.us-west-2.amazonaws.com)|52.218.152.33|:443... connected. HTTP request sent, awaiting response... 403 Forbidden 2021-10-20 15:40:30 ERROR 403: Forbidden. – user10664542 Oct 20 '21 at 21:54
  • 1
    `aws lambda get-function --function-name $functionName --query 'Code.Location'` returns the url enclosed in double quotes, they need to be removed before using `wget`. To remove the quotes you can add the option `--output text`. – razz Nov 02 '21 at 15:05
4

Here is a bash script that I used, it downloads all the functions in the default region:

download_code () {
    local OUTPUT=$1
    OUTPUT=`sed -e 's/,$//' -e 's/^"//'  -e 's/"$//g'  <<<"$OUTPUT"`
    url=$(aws lambda get-function --function-name get-marvel-movies-from-opensearch --query 'Code.Location' )
    wget $url -O $OUTPUT.zip
}

FUNCTION_LIST=$(aws lambda list-functions --query Functions[*].FunctionName)
for run in $FUNCTION_LIST
do
    download_code $run
done

echo "Finished!!!!"
kumarahul
  • 396
  • 4
  • 10
  • We can add a `grep` and download functions with common pattern.`FUNCTION_LIST=$(aws lambda list-functions --query Functions[*].FunctionName | grep )` – kumarahul Nov 22 '21 at 04:49
3

If you want to download all the functions in the given region here is my workaround. I have created a simple node script to download function. Install all the required npm packages and set your AWS CLI to the region you want before running the script.

let download = require('download-file');
let extract = require('extract-zip');
let cmd = require('node-cmd');

let downloadFile = async function (dir, filename, url) {
    let options = {
        directory: dir,
        filename: filename
    }
    return new Promise((success, failure) => {
        download(url, options, function (err) {
            if (err) {
                failure(err)
            } else {
                success('done');
            }
        })
    })
}

let extractZip = async function (source, target) {
    return new Promise((success, failure) => {
        extract(source, { dir: target }, function (err) {
            if (err) {
                failure(err)
            } else {
                success('done');
            }
        })
    })
}

let getAllFunctionList = async function () {
    return new Promise((success, failure) => {
        cmd.get(
            'aws lambda list-functions',
            function (err, data, stderr) {
                if (err || stderr) {
                    failure(err || stderr)
                } else {
                    success(data)
                }
            }
        );
    })
}

let getFunctionDescription = async function (name) {
    return new Promise((success, failure) => {
        cmd.get(
            `aws lambda get-function --function-name ${name}`,
            function (err, data, stderr) {
                if (err || stderr) {
                    failure(err || stderr)
                } else {
                    success(data)
                }
            }
        );
    })
}

let init = async function () {
    try {
        let { Functions: getAllFunctionListResult } = JSON.parse(await getAllFunctionList());
        let getFunctionDescriptionResult, downloadFileResult, extractZipResult;
        getAllFunctionListResult.map(async (f) => {
            var { Code: { Location: getFunctionDescriptionResult } } = JSON.parse(await getFunctionDescription(f.FunctionName));
            downloadFileResult = await downloadFile('./functions', `${f.FunctionName}.zip`, getFunctionDescriptionResult)
            extractZipResult = await extractZip(`./functions/${f.FunctionName}.zip`, `/Users/malhar/Desktop/get-lambda-functions/final/${f.FunctionName}`)
            console.log('done', f.FunctionName);
        })
    } catch (e) {
        console.log('error', e);
    }
}


init()
Mayur Shingare
  • 306
  • 2
  • 4
  • What do **Functions** do in `let { Functions: getAllFunctionListResult } = JSON.parse(await getAllFunctionList());` in this line – KTM Feb 18 '20 at 06:00
  • it's object destructuring creating new variable getAllFunctionListResult and assigning Functions property of JSON.parse to it – Mayur Shingare Mar 04 '20 at 06:10
  • 1
    How does it handle the versioning that Lambda provides? Does this only download $LATEST ? – KingAndrew Feb 28 '21 at 12:38
2

You can find a python script to download all the lambda functions here.

import os
import sys
from urllib.request import urlopen
import zipfile
from io import BytesIO

import boto3

def get_lambda_functions_code_url():

client = boto3.client("lambda")

lambda_functions = [n["FunctionName"] for n in client.list_functions()["Functions"]]

functions_code_url = []

for fn_name in lambda_functions:
    fn_code = client.get_function(FunctionName=fn_name)["Code"]
    fn_code["FunctionName"] = fn_name
    functions_code_url.append(fn_code)

return functions_code_url


def download_lambda_function_code(fn_name, fn_code_link, dir_path):

    function_path = os.path.join(dir_path, fn_name)
    if not os.path.exists(function_path):
        os.mkdir(function_path)

    with urlopen(fn_code_link) as lambda_extract:
        with zipfile.ZipFile(BytesIO(lambda_extract.read())) as zfile:
            zfile.extractall(function_path)


if __name__ == "__main__":
    inp = sys.argv[1:]
    print("Destination folder {}".format(inp))
    if inp and os.path.exists(inp[0]):
        dest = os.path.abspath(inp[0])
        fc = get_lambda_functions_code_url()
        print("There are {} lambda functions".format(len(fc)))
        for i, f in enumerate(fc):
            print("Downloading Lambda function {} {}".format(i+1, f["FunctionName"]))
            download_lambda_function_code(f["FunctionName"], f["Location"], dest)
    else:
        print("Destination folder doesn't exist")
rAm
  • 1,086
  • 2
  • 16
  • 23
  • How am I supposed to run this from a Mac Terminal ? Should I add aws credentials to this code ? Or is this a glue job ? – Mensch Jul 26 '21 at 13:18
  • @mensch - You can run it after you have installed Python and also installed the Boto3 package: ```pip install boto3```. On you Mac, you also need to get either temporary credentials that give you read access to Lambda or you must [setup the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html) with ```aws configure```. Then, when you run the program, you pass in a folder name to store the code, like this: ```mkdir mycode; python python download_lambda_code.py mycode``` – Michael Behrens Oct 01 '22 at 20:05