在 Cloudformation YAML 中,在多行字符串中使用 Ref(?使用 Fn:Sub)

In Cloudformation YAML, use a Ref in a multiline string (? use Fn:Sub)

假设您有一个 aws 资源,例如

  Resources:
    IdentityPool:
      Type: "AWS::Cognito::IdentityPool"
      Properties:
        IdentityPoolName: ${self:custom.appName}_${self:provider.stage}_identity
        CognitoIdentityProviders:
          - ClientId:
              Ref: UserPoolClient

Ref for "AWS::Cognito::IdentityPool" returns 此资源的 ID。现在假设我想在多行字符串中引用该 id。我试过了

Outputs:  
  AmplifyConfig:
    Description: key/values to be passed to Amplify.configure(config);
    Value: |
      {
        'aws_cognito_identity_pool_id': ${Ref: IdentityPool}, ##<------ Error
        'aws_sign_in_enabled': 'enable',
        'aws_user_pools_mfa_type': 'OFF',
      }

我也尝试过使用 Fn:Sub 但没有成功。

   AmplifyConfig:
      Description: key/values to be passed to Amplify.configure(config);
      Value: 
        Fn::Sub 
          - |
            {
              'aws_cognito_identity_pool_id': '${Var1Name}',
              'aws_sign_in_enabled': 'enable',
            }
          - Var1Name:
              Ref: IdentityPool

有什么办法吗?

我找到了如何使用 Join

来做到这一点
AmplifyConfig:
  Description: key/values to be passed to Amplify.configure(config);
  Value:
    Fn::Join:
      - ''
      - - "{"
        - "\n  'aws_cognito_identity_pool_id':"
        - Ref : IdentityPool
        - "\n  'aws_user_pools_id':"
        - Ref : UserPool
        - "\n  'aws_user_pools_web_client_id':"
        - Ref : UserPoolClient
        - ",\n  'aws_cognito_region': '${self:provider.region}'"
        - ",\n  'aws_sign_in_enabled': 'enable'"
        - ",\n  'aws_user_pools': 'enable'"
        - ",\n  'aws_user_pools_mfa_type': 'OFF'"
        - "\n}"

这可行,但有点难看。我打算暂时不接受这个答案,看看是否有人可以用 Fn::Sub.

展示如何做到这一点

在 YAML 中使用管道符号 | 将以下所有缩进行转换为多行字符串。

一个管道,结合 !Sub 可以让你使用:

  • 你的资源Refreturn很值${YourResource}
  • 他们的 Fn::GetAtt return 值只有一个句点 ${YourResource.TheAttribute}
  • 任何伪参数就像${AWS:region}

!Sub | 一样简单,跳转到下一行并添加适当的缩进。示例:

Resources:
  YourUserPool:
    Type: AWS::Cognito::UserPool
    Properties:
      UserPoolName: blabla

Outputs:
  AmplifyConfig:
    Description: key/values to be passed to Amplify.configure(config);
    Value: !Sub |
      {
        'aws_cognito_identity_pool_id': '${YourUserPool}',
        'aws_sign_in_enabled': 'enable',
        'aws_user_pools_mfa_type': 'OFF',
      }
  AdvancedUsage:
    Description: use Pseudo Parameters and/or resources attributes
    Value: !Sub |
      {
        'aws_region': '${AWS::Region}',
        'user_pool_arn': '${YourUserPool.Arn}',
      }

使用 YAML,您可以简单地编写:

Outputs:  
  AmplifyConfig:
    Description: key/values to be passed to Amplify.configure(config);
    Value: !Sub '
      {
        "aws_cognito_identity_pool_id": "${IdentityPool}",
        "aws_sign_in_enabled": "enable",
        "aws_user_pools_mfa_type": "OFF",
      }'

留在这里是因为我在做类似的事情时遇到了 Base64 编码错误,并且在搜索时出现了这个问题 一个解决方案。

在我的例子中,我使用多行字符串 + !Sub 来填充 UserData 并在 AWS Cloudformation 中收到以下错误。

错误:

Invalid BASE64 encoding of user data. (Service: AmazonEC2; Status Code: 400; Error Code: InvalidUserData.Malformed; Request ID: *; Proxy: null)

解法:

可以通过组合两个内置的 Cloudformation 函数来解决; Fn::Base64!Sub:

UserData: 
    Fn::Base64: !Sub | 
    #!/bin/bash
    echo ${SomeVar}