我有一个AWS Lambda函数,它是由API Gateway API触发的。我想复制这个Lambda函数以及它的触发器。我该如何实现?我尝试使用“创建版本”,但API Gateway触发器并没有被复制,而且我也不能更改代码。
我有一个AWS Lambda函数,它是由API Gateway API触发的。我想复制这个Lambda函数以及它的触发器。我该如何实现?我尝试使用“创建版本”,但API Gateway触发器并没有被复制,而且我也不能更改代码。
目前没有提供复制/克隆Lambda函数和API网关配置的功能。您需要从头开始创建新的函数。
如果您预计将来需要复制函数,使用AWS CloudFormation创建Lambda函数可能是值得的。然后,您可以轻松地在未来部署多个函数。
不幸的是,AWS Web控制台和命令行工具都没有提供在服务中复制函数的功能。
这是一个明显的疏忽,使得处理看似简单的任务变得困难,例如从“模板”函数创建新函数或通过创建具有不同名称的副本来重命名函数(也不能直接实现)。
我发现完成此任务的最简单方法是创建一个Lambda函数,该函数可以复制其他函数。
do_duplicate_function.py
Python 3函数代码可以部署到Lambda上,也可以在本地运行,以复制您AWS账户中的函数。
要使用它,请在AWS控制台中配置测试事件,或使用至少包含以下内容的事件数据调用该函数:
{
"SourceFunctionName": "function_name_to_copy",
"FunctionName": "function_name_to_create"
}
SourceFunctionName
是要复制的函数的名称,FunctionName
是要创建的函数的名称。
有关如何使用和部署此功能的更多文档在函数代码顶部本身有说明,请参阅代码以获取详细信息。
注意:我已在此小帖子中单独编写了它,您也可以获得do_duplicate_function.py函数代码文件。请在那里查看最新版本。我也在这里放置了所有内容,以使此答案完整且自包含。
"""
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))
#!/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}"
对我来说,有一种更简单的方法可以做到这一点:
将导出的部署包压缩文件加载到 S3 中,然后使用 S3 路径创建新的部署包。如果出现问题或需要进行其他操作,这样做会快速且容易。