Почему пользовательский ресурс не смог стабилизироваться в ожидаемое время в AWS Cloudformation? - PullRequest
0 голосов
/ 02 апреля 2020

Я хочу создать новый пользовательский ресурс с CloudFormation, чтобы получить результат текущей даты минус X дней, и когда я создаю лямбда-функцию, я получаю ошибку: не удалось стабилизировать ресурс в ожидаемое время.

Мой код:

AWSTemplateFormatVersion: 2010-09-09
Parameters:
  Environment:
    Description: Environment
    Type: String
    Default: dev
    AllowedValues:
      - dev
      - test
      - prod
      - sbx
  DaysToSubstract:
    Description: Days To Substract to calculate dates to ingest with RedshiftLoader
    Type: Number
    Default: 1
Resources:
  lambdaDateRedshiftLoader:
    Type: 'AWS::Lambda::Function'
    DependsOn:
      - lambdaDateRedshiftLoaderRole
    Properties:
      Code:
        ZipFile: !Sub |
          from datetime import date, timedelta
          import cfnresponse
          def lambda_handler(event, context):
              current_delta = date.today() - timedelta(days=event['DaysToSubstract'])
              current_delta_str = current_delta.strftime("%Y-%m-%d")
              responseData['Dates'] = current_delta_str
              cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData)
      Environment:
        Variables:
          DaysToSubstract: !Sub '${DaysToSubstract}'
      Description: >-
        Calculate yesterday date to obtain start and end date to load the data
        with RedshiftLoader
      Handler: index.lambda_handler
      MemorySize: 128
      Role: !GetAtt lambdaDateRedshiftLoaderRole.Arn
      Runtime: python3.7
      Timeout: 30
  lambdaDateRedshiftLoaderRole:
    Type: 'AWS::IAM::Role'
    Properties:
      RoleName: !Sub 'a3m${Environment}-datesRL-lambda-role'
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Action:
              - 'sts:AssumeRole'
            Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
      Path: /service-role/
      Policies:
        - PolicyName: !Sub 'a3m${Environment}-lambda-datesRL-lambda-logs-policy'
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Action:
                  - 'logs:CreateLogGroup'
                  - 'logs:CreateLogStream'
                  - 'logs:PutLogEvents'
                Effect: Allow
                Resource:
                  - !Sub >-
                    arn:aws:logs:eu-west-1:${AWS::AccountId}:log-group:/aws/lambda/lambda-datesRL-uyc:*
  lambdaRL:
    Type: 'Custom::Value'
    Properties:
      ServiceToken: !GetAtt lambdaDateRedshiftLoader.Arn
Outputs:
  LambdaFunctionOutput:
    Value: !GetAtt lambdaRL.Dates
    Description: Return Value of Lambda Function (Date minus x days)

Я использую cfnresponse с SUCCESS и использую! GetAtt lambdaRL.Dates в выходных данных.

Заранее спасибо

1 Ответ

0 голосов
/ 03 апреля 2020

Ваша лямбда-функция выдавала ошибки , поэтому у нее никогда не было возможности вызвать cfnresponse.send(). Это означало, что CloudFormation продолжала ждать ответа.

Вот обновленная версия лямбда-функции:

from datetime import date, timedelta
import cfnresponse, os

def lambda_handler(event, context):
    current_delta = date.today() - timedelta(days=int(os.environ['DaysToSubtract']))
    current_delta_str = current_delta.strftime("%Y-%m-%d")
    responseData = {}
    responseData['Dates'] = current_delta_str
    cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData)

Проблемы были:

  • Переменные среды передаются через os.environ(), а не event()
  • Значение DaysToSubtract проходило как string, а не int, поэтому функция timedelta() не работала (Осторожно ... правописание Substract против Subtract)
  • Словарь responseData не был инициализирован, поэтому он выдавал ошибку NameError: name 'responseData' is not defined

Я настоятельно рекомендую вам сначала разработайте лямбда-функции в консоли . Затем, когда они будут работать, переместите их в шаблон CloudFormation. Это значительно упрощает отладку.

О, также обратите внимание, что Пользовательские ресурсы вызываются при создании, обновлении и удалении стека . Это может привести к неожиданному поведению, особенно во время операции Delete. Обычно хорошей идеей является вставка оператора if для запуска кода только на этапе Create с помощью:

if event['RequestType'] == 'Create':
...