如何更新在 Python 2.7/3.6/3.7 上執行的 AWS Lambda 函數的 AWS CloudFormation cfn-response 模組?

3 分的閱讀內容
0

我想要更新在 Python 2.7/3.6/3.7 上執行的 AWS Lambda 函數的 AWS CloudFormation cfn-response 模組。

解決方案

**注意事項:**下列步驟僅適用於在 Python 2.7/3.6/3.7 上執行的 Lambda 函數。下列命令適用於 Linux 和 macOS 環境。Windows PowerShell 上的語法可能會有所不同。

**注意事項:**如果您在執行 AWS Command Line Interface (AWS CLI) 命令時收到錯誤訊息,請確認您使用的是最新的 AWS CLI 版本

1.    如需尋找包含自訂資源的堆疊,請執行以下命令:

aws cloudformation list-stacks --region us-east-1 | grep -oE 'arn:[^"]+' | while read arn; do aws cloudformation list-stack-resources --stack-name $arn --region us-east-1 | grep -E '(Custom::)|(::CustomResource)' | awk '{print $2}' | while read resource; do if [[ -n $resource ]]; then echo $arn; echo $resource; fi; done; done

您應該會看到類似於下列範例的輸出:

arn:aws:cloudformation:us-east-1:123456789012:stack/TestStack/3497b950-55f1-11eb-aad4-124a026c8667
"ResourceType": "AWS::CloudFormation::CustomResource",

2.    若要尋找與自訂資源相關聯的 Lambda 函數,請執行下列命令,從堆疊的範本檢查自訂資源的 ServiceToken 屬性:

aws cloudformation get-template --stack-name TestStack | jq -r .TemplateBody

**注意事項:**步驟 2 中的命令會使用 jq 選項 (來自 jq 網站) 預覽堆疊的範本以格式化回應。

您應該會看到類似於下列範例的輸出:

Resources:
  MyCustomResource:
    Type: AWS::CloudFormation::CustomResource
    Properties:
      ServiceToken: !GetAtt MyFunction.Arn
      Name: "John"
  MyFunction:
    Type: AWS::Lambda::Function
    Properties:
      Handler: index.handler
      Role: !GetAtt MyRole.Arn
      Runtime: python3.7
      Code:
        ZipFile: |
          import cfnresponse
          def handler(event, context):
            responseData = {'Message': 'Hello {}!'.format(event['ResourceProperties']['Name'])}
            cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, "CustomResourcePhysicalID")
  MyRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - sts:AssumeRole
      ManagedPolicyArns:
        - "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
Outputs:
  Result:
    Value: !GetAtt MyCustomResource.Message

注意事項:您從步驟 2 的輸出中取得的範本是 Lambda 支援的自訂資源的最小範本範例。該ServiceToken: !GetAtt MyFunction.Arn 屬性在 MyCustomResource 區段中。由 ServiceToken 屬性的 !GetAtt MyFunction**.Arn** 解析的值不是 Amazon Simple Notification Service (Amazon SNS) 主題的 Amazon Resource Name (ARN) 就是 Lambda 函數。

3.    在步驟 2 的範本中,識別 Lambda 函數的定義位置。

如果您的 Lambda 函數與自訂資源位於相同的堆疊中,請跳至步驟 4。例如,步驟 2 中的 Fn::GetAtt 函數會顯示 Lambda 函數定義在與自訂資源相同的範本中。

如果 ServiceToken 屬性指向寫在程式中的 ARN,則 Lambda 函數可能在另一個堆疊中。如果已透過 Fn::Import 解析 ServiceToken 屬性,則請使用 AWS CloudFormation 中的 list-exports API 來查詢值。例如:

aws cloudformation list-exports --region us-east-1
{
    "Exports": [
        {
            "ExportingStackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/SomeOtherStack/481dc040-b283-11e9-b1bd-12d607a4fd1c",
            "Value": "arn:aws:lambda:us-east-1:123456789012:function:SomeOtherStack-MyFunction-5ZE2CQO8RAA9",
            "Name": "MyExport"
        }
    ]
}

然後,使用 list-tags 檢查位於個別堆疊中的函數標籤,以尋找 AWS CloudFormation 堆疊 ARN。例如:

aws lambda list-tags --resource arn:aws:lambda:us-east-1:123456789012:function:TestStack-MyFunction-5ZE2CQO8RAA9 | grep stack-id

您會收到類似於下列內容的輸出:

"aws:cloudformation:stack-id": "arn:aws:cloudformation:us-east-1:123456789012:stack/TestStack/3497b950-55f1-11eb-aad4-124a026c8667"

**注意事項:**您還可以在 AWS Lambda 主控台中找到](https://docs.aws.amazon.com/lambda/latest/dg/configuration-tags.html)標籤[函數。

4.    若要允許 AWS CloudFormation 在 Lambda 函數中載入最新的 cfn-response 模組,請更新 Lambda 函數的內嵌原始碼。例如:

Code:
        ZipFile: |
          import cfnresponse
          def handler(event, context):
            responseData = {'Message': 'Hello {}!'.format(event['ResourceProperties']['Name'])}
            cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, "CustomResourcePhysicalID")

**注意事項:**如需具有內嵌原始碼的 Lambda 函數的範例範本,請參閱步驟 2。

現在,AWS CloudFormation 會將下列 cfn-response 模組代碼範例載入至您的 Lambda 函數。例如:

from botocore.vendored import requests
import json

SUCCESS = "SUCCESS"
FAILED = "FAILED"

def send(event, context, responseStatus, responseData, physicalResourceId=None, noEcho=False):
    responseUrl = event['ResponseURL']

    print(responseUrl)

    responseBody = {}
    responseBody['Status'] = responseStatus
    responseBody['Reason'] = 'See the details in CloudWatch Log Stream: ' + context.log_stream_name
    responseBody['PhysicalResourceId'] = physicalResourceId or context.log_stream_name
    responseBody['StackId'] = event['StackId']
    responseBody['RequestId'] = event['RequestId']
    responseBody['LogicalResourceId'] = event['LogicalResourceId']
    responseBody['NoEcho'] = noEcho
    responseBody['Data'] = responseData

**注意事項:**如需相關資訊,請參閱 cfn-response 模組的「模組原始碼」區段中的代碼範例。

cfn-response 模組代碼範例會在 Lambda 函數的部署套件中使用 botocore.requests

若要將 cfn-response 模組更新為使用 urllib3 的最新版本,請在 AWS CloudFormation 範本中更新函數的內嵌代碼。透過將備註新增至內嵌 Lambda 函數代碼來執行此動作。例如:

ZipFile: |
           import cfnresponse
           def handler(event, context):
+            # This comment was added to force an update on this function's code
             responseData = {'Message': 'Hello {}!'.format(event['ResourceProperties']['Name'])}
             cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, "CustomResourcePhysicalID")
   MyRole:

5.    將任何變更儲存至包含 Lambda 函數的範本。

6.    更新您的堆疊

在堆疊完成更新後,即會修改 cfn-response 模組。

**注意事項:**如果您的函數代碼位於Amazon Simple Storage Service (Amazon S3) 儲存貯體或 Amazon Elastic Container Registry (Amazon ECR) 映像檔中,您必須自行更新模組,以包含 urllib3 的版本。若要取得最新版本的 cfn-response 模組的原始碼,請參閱 cfn-response 模組

**注意事項:**如果新的 Python 或 JavaScript 執行時引入了重大變更,則您必須更新 cfn-response 模組。無需再次更新 ZipFile,無論何時更新函數的 Runtime 屬性,您都可以自動連接最新版本的 ** cfn-response ** 模組。


AWS 官方
AWS 官方已更新 3 年前