Come posso aggiornare il modulo cfn-response di AWS CloudFormation per le funzioni AWS Lambda in esecuzione su Python 2.7/3.6/3.7?

5 minuti di lettura
0

Desidero aggiornare il modulo cfn-response di AWS CloudFormation per le funzioni di AWS Lambda in esecuzione su Python 2.7/3.6/3.7.

Risoluzione

Nota: i passaggi seguenti sono applicabili solo alle funzioni Lambda in esecuzione su Python 2.7/3.6/3.7. I seguenti comandi sono applicabili agli ambienti Linux e macOS. La sintassi può variare in Windows PowerShell.

Nota: Se riscontri degli errori durante l'esecuzione dei comandi dell’interfaccia della linea di comando AWS (AWS CLI), assicurati di utilizzare la versione più recente dell'AWS CLI.

  1. Per trovare gli stack che contengono risorse personalizzate, esegui il seguente comando:
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

Dovresti vedere un output simile al seguente output di esempio:

arn:aws:cloudformation:us-east-1:123456789012:stack/TestStack/3497b950-55f1-11eb-aad4-124a026c8667
"ResourceType": "AWS::CloudFormation::CustomResource",
  1. Per trovare la funzione Lambda associata alla risorsa personalizzata, esegui il seguente comando per verificare la proprietà ServiceToken della risorsa personalizzata dal modello dello stack:
aws cloudformation get-template --stack-name TestStack | jq -r .TemplateBody

Nota: il comando nel passaggio 2 visualizza l'anteprima del modello dello stack utilizzando l'opzione jq (dal sito Web jq) per formattare la risposta.

Dovresti vedere un output simile al seguente output di esempio:

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

Nota: il modello ottenuto dall'output del passaggio 2 è un esempio di modello minimo per una risorsa personalizzata supportata da Lambda. La proprietà ServiceToken: !GetAtt MyFunction.Arn si trova nella sezione MyCustomResource. Il valore risolto da**!GetAtt** MyFunction**.Arn** della proprietà ServiceToken è il nome della risorsa Amazon (ARN) dell'argomento Amazon Simple Notification Service (Amazon SNS) o la funzione Lambda.

  1. Nel modello del passaggio 2, identifica dove è definita la tua funzione Lambda.

Se la tua funzione Lambda è nello stesso stack della risorsa personalizzata, vai al passaggio 4. Ad esempio, la funzione Fn::GetAtt nel passaggio 2 mostra che la funzione Lambda è definita nello stesso modello della risorsa personalizzata.

Se la proprietà ServiceToken punta a un ARN codificato, la funzione Lambda potrebbe trovarsi in un altro stack. Se la proprietà ServiceToken viene risolta tramite Fn::Import, utilizza l'API list-exports in AWS CloudFormation per cercare il valore. Ad esempio:

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"
        }
    ]
}

Quindi, controlla i tag di funzione situati in uno stack separato utilizzando list-tags per individuare lo stack ARN dello stack AWS CloudFormation. Ad esempio:

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

Riceverai un output simile al seguente:

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

Nota: puoi anche trovare i tag delle funzioni nella console AWS Lambda.

  1. Per consentire ad AWS CloudFormation di caricare il modulo cfn-response più recente nella tua funzione Lambda, aggiorna il codice sorgente in linea della tua funzione Lambda. Ad esempio:
Code:
        ZipFile: |
          import cfnresponse
          def handler(event, context):
            responseData = {'Message': 'Hello {}!'.format(event['ResourceProperties']['Name'])}
            cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, "CustomResourcePhysicalID")

Nota: vedi il passaggio 2 per un modello di esempio con una funzione Lambda con codice sorgente in linea.

Ora, il seguente esempio di codice del modulo cfn-response viene caricato da AWS CloudFormation nella tua funzione Lambda. Ad esempio:

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

Nota: per ulteriori informazioni, consulta gli esempi di codice nella sezione "Codice sorgente del modulo cfn-response".

L'esempio di codice del modulo cfn-response utilizza botocore.requests nel pacchetto di distribuzione della funzione Lambda.

Per aggiornare il modulo cfn-response all'ultima versione che utilizza urllib3, aggiorna il codice in linea della funzione nel modello AWS CloudFormation. A tale scopo, aggiungi un commento al codice della funzione Lambda in linea. Ad esempio:

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:
  1. Salva le modifiche al modello che contiene la tua funzione Lambda.

  2. Aggiorna il tuo stack.

Il modulo cfn-response viene modificato al termine dell'aggiornamento dello stack.

Nota: se il codice della funzione risiede in un bucket Amazon Simple Storage Service (Amazon S3) o in un'immagine Amazon Elastic Container Registry (Amazon ECR), devi aggiornare tu stesso il modulo per includere la versione con urllib3. Per ottenere il codice sorgente per l'ultima versione del modulo cfn-response, consulta il modulo cfn-response.

Nota: se un nuovo runtime Python o JavaScript introduce una modifica sostanziale, devi aggiornare il modulo cfn-response. Invece di aggiornare nuovamente lo ZipFile, puoi allegare automaticamente la versione più recente del modulo cfn-response ogni volta che la proprietà Runtime di una funzione viene aggiornata.


AWS UFFICIALE
AWS UFFICIALEAggiornata 3 anni fa