AWS:如何在YAML数据库名称中使用转换cloudformation函数

时间:2020-08-26 17:30:11

标签: amazon-web-services amazon-cloudformation

尝试合并似乎无法正常工作的两个代码功能有些困难。 aws cloudformation cli工具似乎有问题并抛出错误:'list' object has no attribute 'get'

我试图指定一个lambda函数(类型AWS :: Serverless :: Function),该函数本来可以工作,但是我想将Event Schedule对象指定为小写(对于数据库是必需的)。

有问题的代码,最后8行是问题:

Resources:
  UpdatePartitionsLogTableFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: updatePartitionsTable.handler
      Runtime: nodejs12.x
      CodeUri: src
      Description: Updates partitions Athena tables
      MemorySize: 128
      Timeout: 60
      Policies:
        - Version: "2012-10-17"
          Statement:
            - Effect: Allow
              Action:
                - "athena:*"
              Resource:
                - "*"
            - Effect: Allow
              Action:
                - "glue:*"
              Resource:
                - "*"
            - Effect: Allow
              Action:
                - "s3:*"
              Resource:
                - "*"
      Events:
        Timer:
          Type: Schedule
          Properties:
            Schedule: cron(0 * * * ? *)
            Input:
              'Fn::Transform':
              - Name: 'String'
                Parameters:
                  InputString: !Sub |
                      {"database": "${AWS::StackName}_logs",
                        "tableNames": "${PartitionedTables}"}
                  Operation: Lower

我得到一个错误:

'list' object has no attribute 'get'

简化代码:

            Input: !Sub |
                {"database": "${AWS::StackName}_logs",
                  "tableNames": "${PartitionedTables}"}

如果我简化了代码,则不会出错,但是我的用例需要小写字母。 有人可以帮忙吗?我有点卡住。

1 个答案:

答案 0 :(得分:1)

在@Marcin的帮助下,我设法解决了这个问题 不幸的是,我遇到了其他部署问题的麻烦,所以我想发表我的最终发现作为对这个问题的答案。我希望这可以帮助其他人。

在我最初的问题中,确实有一个-引起了问题,需要删除它并解决第一个错误。

下面的工作代码: (别忘了对相同模板和其他模板中对数据库的任何引用进行类似的转换,可以使用相同的宏转换代码)

            Input:
              'Fn::Transform':
                Name: 'StringTransform'
                Parameters:
                  InputString: !Sub |
                      {"database": "${AWS::StackName}_logs",
                        "tableNames": "${PartitionedTables}"}
                  Operation: Lower

完成这项工作所需的CloudFormation宏Lambda代码:

Resources:
  # Custom Transform Macro Function
  # Function is called to manipulate (transform) strings
  TransformFunction:
    Type: AWS::Lambda::Function
    Properties:
      Code:
        ZipFile: |
          import traceback


          def handler(event, context):
              response = {
                  "requestId": event["requestId"],
                  "status": "success"
              }
              try:
                  operation = event["params"]["Operation"]
                  input = event["params"]["InputString"]
                  no_param_string_funcs = ["Upper", "Lower", "Capitalize", "Title", "SwapCase"]
                  if operation in no_param_string_funcs:
                      response["fragment"] = getattr(input, operation.lower())()
                  elif operation == "Strip":
                      chars = None
                      if "Chars" in event["params"]:
                          chars = event["params"]["Chars"]
                      response["fragment"] = input.strip(chars)
                  elif operation == "Replace":
                      old = event["params"]["Old"]
                      new = event["params"]["New"]
                      response["fragment"] = input.replace(old, new)
                  elif operation == "MaxLength":
                      length = int(event["params"]["Length"])
                      if len(input) <= length:
                          response["fragment"] = input
                      elif "StripFrom" in event["params"]:
                          if event["params"]["StripFrom"] == "Left":
                              response["fragment"] = input[len(input)-length:]
                          elif event["params"]["StripFrom"] != "Right":
                              response["status"] = "failure"
                      else:
                          response["fragment"] = input[:length]
                  else:
                      response["status"] = "failure"
              except Exception as e:
                  traceback.print_exc()
                  response["status"] = "failure"
                  response["errorMessage"] = str(e)
              return response

      Handler: index.handler
      Runtime: python3.7
      Role: !GetAtt TransformExecutionRole.Arn
      FunctionName: !Sub ${AWS::StackName}-StringTransform

宏的其他随附资源:

  # Role for TransformFunction
  TransformExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service: [lambda.amazonaws.com]
            Action: ['sts:AssumeRole']
      Path: /
      Policies:
        - PolicyName: root
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action: ['logs:*']
                Resource: 'arn:aws:logs:*:*:*'
  # Permission for TransformFunction
  TransformFunctionPermissions:
    Type: AWS::Lambda::Permission
    Properties:
      Action: 'lambda:InvokeFunction'
      FunctionName: !GetAtt TransformFunction.Arn
      Principal: 'cloudformation.amazonaws.com'
  # Actual CloudFormationMacro entrypoint for TransformFunction
  Transform:
    Type: AWS::CloudFormation::Macro
    Properties:
      Name: 'StringTransform'
      Description: Provides various string processing functions
      FunctionName: !GetAtt TransformFunction.Arn

再次感谢@Marcin