Rajarshi Das
Rajarshi Das

Reputation: 12340

How to copy or duplicate an AWS Lambda function

I have an AWS Lambda function that is triggered from an API Gateway API. I want to duplicate this Lambda function including the triggers. How can I do this? I tried using "create version" but the API Gateway trigger is not duplicating and I am not able to change the code.

Upvotes: 38

Views: 63176

Answers (6)

For me, there's an easier way to do this:

Take the exported deployment package zip, load it into S3, then create your new deployment package using the S3 path. Then if something goes wrong or you need to do something different, its quick and easy.

Upvotes: 0

Miraj
Miraj

Reputation: 83

If you need to duplicate or copy a lambda funtion. You can use Export function from the Actions.

enter image description here

Once you click on Export funtion enter image description here

This will give you two download options:

1. Download AWS SAM file: this will give you the YAML file with your current lambda function's configurations (such as Triggers, Environment variables, VPC).

Note: You can use this YAML file in AWS CloudFormation and create your duplicate lambda with the current lambda configuration.

2. Download deployment package: this will give you the zip file of your current code.

in this case, you can create a new lambda and upload the zip file there and use it.

enter image description here

Note: this will not have your current lambda configuration it will only have the code of your current lambda.

Upvotes: 4

Leo
Leo

Reputation: 1250

Here's a simple bash/jq script that works for docker image lambdas in a VPC, just in case you don't fancy running a Lambda to create another lambda, or CloudFormation:

#!/bin/bash

export SRC_FUNC=$1
export DST_FUNC=$2

origFunc=$(aws lambda get-function --function-name $SRC_FUNC)
ImageConfig=$(echo $origFunc | jq '.Configuration.ImageConfigResponse')
Code=$(echo $origFunc| jq '.Code' | jq 'del(.ResolvedImageUri)' | jq 'del(.RepositoryType)')
echo "code = $Code"

cleanConf=$(echo $origFunc | \
           jq 'del(.Code)' | \
           jq 'del(.Configuration.ImageConfigResponse)'|\
           jq 'del(.Configuration.FunctionName)' |\
           jq 'del(.Configuration.FunctionArn)' |\
           jq 'del(.Configuration.CodeSize)' |\
           jq 'del(.Configuration.LastModified)' |\
           jq 'del(.Configuration.CodeSha256)' |\
           jq 'del(.Configuration.Version)' |\
           jq 'del(.Configuration.VpcConfig.VpcId)' |\
           jq 'del(.Configuration.RevisionId)' |\
           jq 'del(.Configuration.State)' |\
           jq 'del(.Configuration.LastUpdateStatus)' |\
           jq '.Configuration')

finalConf=$(echo "${cleanConf}   ${ImageConfig} { \"Code\":${Code} }"  | jq -s add)

#echo $finalConf

aws lambda create-function --function-name $DST_FUNC --cli-input-json "${finalConf}"

To run this, just pass the source and destination lambda names as arguments in this order.

Upvotes: 0

Emmanuel
Emmanuel

Reputation: 5403

When editing a lambda function, you can go Actions > Export Function > Download deployment package.

enter image description here

This downloads a .zip file of the function.

Then create a new Lambda, and go "Upload from" (right above the code editor) > ".zip file"

enter image description here

This duplicates the code and npm modules etc... Not the triggers or permissions of the function though.

Upvotes: 34

James Murty
James Murty

Reputation: 1858

Use a Lambda function to duplicate other functions

Unfortunately neither the AWS web console nor the command line tools have a feature to duplicate a function in the service.

This is a glaring oversight that makes it difficult to do seemingly simple things, like create new functions from a "template" function or rename a function (which is also not possible directly) by creating a copy with a different name.

The easiest way I have found to do this job is to create a Lambda function that duplicates other functions.

The do_duplicate_function.py Python 3 function code below can be deployed to Lambda, or be run locally, to duplicate a function in your AWS account.

To use it, configure a test event in the AWS console or otherwise invoke the function with event data containing at least:

{
    "SourceFunctionName": "function_name_to_copy",
    "FunctionName": "function_name_to_create"
}

Where SourceFunctionName is the name of a function to be duplicated, and FunctionName is the name of the function to create.

There is more documentation at the top of the function code itself about how to use it and deploy it, see the code for details.

Note: I have written this up separately in this mini-post where you can also get the do_duplicate_function.py function code file. Check there for the latest version. I have put everything here as well so this answer would be complete and self-contained.

"""
This is a Python 3 utility function that creates a duplicate copy of another
function in this AWS account with the same configuration settings, environment
variables, etc.

In short, this does the job that should be handled by a "Duplicate" feature
that is missing from the AWS console and CLI.


Usage in AWS
------------

To use this function, configure a test event in the AWS console or otherwise
invoke the function with event data containing at least:


    {
        "SourceFunctionName": "function_name_to_copy",
        "FunctionName": "function_name_to_create"
    }

Where `SourceFunctionName` is the name of a function to be duplicated, and
`FunctionName` is the name of the function to create.

You can override configuration settings of the new function copy by including
extra optional variables in the event data like `Description`, `Timeout`,
`MemorySize`, etc to have your provided values override the values of the
source function's configuration.

See the parameters for the boto3 `create_function()` method for details:
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/lambda.html#Lambda.Client.create_function


Usage locally
-------------

You can run this function locally without needing to deploy it to AWS Lambda at
all provided you meet these requirements:

- run it within a python3 virtualenv with `boto3` installed
- set up an AWS profile and credentials as for the AWS CLI tool, with
  sufficient permissions to do the work.

Once you have these in place, run the function like this:

    AWS_PROFILE=your-aws-profile \
        python3 do_duplicate_function.py \
        '{"SourceFunctionName": "fn_to_copy", "FunctionName": "fn_to_create"}'


Deployment to AWS
-----------------

Deploy this function with the Python 3.8 runtime (it might work on earlier
versions of Python 3 but hasn't been tested).

This function must have sufficient permissions to fetch and create Lambda
functions and to pass copy roles to the new function. To permit this, apply
something like the following permissions policy document to the deployed
function:

    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Action": [
                    "lambda:CreateFunction",
                    "lambda:ListFunctions",
                    "lambda:GetFunction",
                    "iam:GetRole",
                    "iam:PassRole"
                ],
                "Resource": "*"
            }
        ]
    }

Author: James Murty (https://github.com/jmurty) License: MIT
"""
import os
import json
import sys

import boto3
import urllib3


def lambda_handler(event, context):
    # Optional envvar, only used to run functions locally
    aws_profile = os.environ.get("AWS_PROFILE")
    if aws_profile:
        session = boto3.Session(profile_name=aws_profile)
        lambda_client = session.client("lambda")
    else:
        lambda_client = boto3.client("lambda")

    # Fetch source function metadata
    function_data = lambda_client.get_function(
        FunctionName=event.pop("SourceFunctionName"),
        Qualifier=event.pop("SourceFunctionVersion", "$LATEST"),
    )
    function_data.pop("ResponseMetadata")

    # Download function code from temporary URL
    code_url = function_data.pop("Code")["Location"]
    http = urllib3.PoolManager()
    response = http.request("GET", code_url)
    if not 200 <= response.status < 300:
        raise Exception(f"Failed to download function code: {response}")
    function_code = response.data

    # Build metadata for new function based on original function's
    new_function_data = {
        n: v
        for n, v in function_data["Configuration"].items()
        if n in (
            "Runtime",
            "Role",
            "Handler",
            "Description",
            "Timeout",
            "MemorySize",
            "Publish",
            "Environment",
        )
    }
    # Override function metadata values with those provided in event
    new_function_data.update(event)
    # Provide function code zip data
    new_function_data["Code"] = {"ZipFile": function_code}

    # Create a new function
    return lambda_client.create_function(**new_function_data)


# Support running this function locally
if __name__ == "__main__":
    if len(sys.argv) < 2:
        print(f"Usage: {sys.argv[0]} <EVENT_JSON_TEXT_OR_FILE>")
        sys.exit(1)

    # Parse event data from JSON file path, or literal JSON
    try:
        with open(sys.argv[1], "rt") as f:
            event = json.load(f)
    except Exception:
        event = json.loads(sys.argv[1])

    context = None

    print(lambda_handler(event, context))

Upvotes: 9

John Rotenstein
John Rotenstein

Reputation: 270104

There is no provided function to copy/clone Lambda Functions and API Gateway configurations. You will need to create new a new function from scratch.

If you envision having to duplicate functions in the future, it may be worthwhile to use AWS CloudFormation to create your Lambda Functions. You can then easily deploy more in future.

Upvotes: 21

Related Questions