【问题标题】:Cloud Formation Function from Custom Resource来自自定义资源的云形成函数
【发布时间】:2018-07-03 15:29:33
【问题描述】:

我有一个 CF 模板,我在其中提供了一个参数,并对其进行条件检查以确定如何构造存储桶名称。如果是产品,它应该是“名称”。如果不是 prod,它应该是这样的“name_environment”:

# # # # # # # # # # # # # # # #
#                             #
#  Input Parameters           #
#  Prefix: t3st-acc0un7-123   #
#   Stage: dev                #
#                             #
#  Expected S3 Name Output    #
#  t3st-acc0un7-123-dev       #
#  t3st-acc0un7-123-dev-2     #
#                             #
# # # # # # # # # # # # # # # #
#                             #
#  Input Parameters           #
#  Prefix: t3st-acc0un7-123   #
#   Stage: prod               #
#                             #
#  Expected S3 Name Output    #
#  t3st-acc0un7-123           #
#  t3st-acc0un7-123-2         #
#                             #
# # # # # # # # # # # # # # # #

这是我的模板:

Parameters:
  Prefix:
    Type: String
    Default: t3st-acc0un7-123
  Stage:
    Type: String
    AllowedPattern: "([a-z]|[0-9])+"

Conditions:
  IsProdStage:
    Fn::Equals:
    - !Ref Stage
    - prod

Resources:
  TestBucket:
      Type: AWS::S3::Bucket
      Properties:
        BucketName: 
          Fn::If:
          - IsProdStage
          - !Ref Prefix
          - !Join
            - '-'
            - 
              - !Ref Prefix
              - !Ref Stage

  TestBucket2:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: 
        Fn::If:
        - IsProdStage
        - !Join
          - '-'
          -
            - !Ref Prefix
            - '2'
        - !Join
          - '-'
          - 
            - !Ref Prefix
            - !Ref Stage
            - '2'

在第一个示例模板中,条件和连接逻辑是重复的。我基本上想将条件的值存储在某个地方以从每个后续函数中调用,而不是复制逻辑。

在下一个示例中,我尝试使用自定义资源来调用虚拟 lambda(因为需要 ServiceToken),因此我可以在 上设置 Value 属性>TestCustomResource 基于条件和输入的自定义资源,并从我创建的其他资源中读取。

Parameters:
  Prefix:
    Type: String
    Default: t3st-acc0un7-123
  Stage:
    Type: String
    AllowedPattern: "([a-z]|[0-9])+"

Conditions:
  IsProdStage:
    Fn::Equals:
    - !Ref Stage
    - prod

Resources:
  TestBucket:
      Type: AWS::S3::Bucket
      Properties:
        BucketName: !GetAtt TestCustomResource.Value

  TestBucket2:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Join
        - '-'
        -
          - !GetAtt TestCustomResource.Value
          - 2

  TestCustomResource:
    Type: Custom::Codswallop
    Properties:
      ServiceToken: !GetAtt DummyLambda.Arn
      Value:
        Fn::If:
        - IsProdStage
        - !Ref Prefix
        - !Join
          - '-'
          - 
            - !Ref Prefix
            - !Ref Stage

  DummyLambda:
    Type: "AWS::Lambda::Function"
    Properties:
      Code: 
        ZipFile: >
          print("")
      Handler: lambda_function.lambda_handler
      Role: !GetAtt DummyRole.Arn
      Runtime: python3.6

  DummyRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
            - Effect: Allow
              Principal:
                Service:
                  - lambda.amazonaws.com
              Action:
                - sts:AssumeRole
      RoleName: DummyRole

我知道虚拟 lambda 有点 hacky,但这似乎是一个非常有用的功能,能够存储计算值以供在模板周围使用。第二个示例给出如下错误:TestCustomResource - 自定义资源未能在预期时间内稳定。

(答案可能是使用多个依赖于先前 CF 输出值或嵌套模板的模板。)

【问题讨论】:

    标签: amazon-web-services amazon-cloudformation


    【解决方案1】:

    请勿将自定义资源用于虚假目的。

    该函数需要在操作完成后“回调”到 CloudFormation。您的自定义资源没有代码,因此它永远不会回调,因此您的模板永远不会完成。

    如果您的第一个示例有效,请坚持使用。您的第二个选项(除了不工作)对于未来的 IT 人员来说很难理解和维护。

    始终通过优雅的 hack 实现轻松的未来维护。 (由一个不得不维护其他人的优雅技巧的人说。)

    【讨论】:

    • 公平点,但是为了澄清自定义资源没有被用于虚假目的,它可以集中条件逻辑和存储桶名称构造,因此其余资源不必复制逻辑。
    • 除了结果是下一人理解的两倍长和更复杂的东西。 (而且不起作用。)相反,只需使用 !Sub 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:vpc/${vpc}' 之类的语法来简化您的第一个版本,从而避免使用 Join
    猜你喜欢
    • 1970-01-01
    • 2017-03-17
    • 2021-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-16
    相关资源
    最近更新 更多