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

23
Imagine你拥有一个AWS资源,比如说:
  Resources:
    IdentityPool:
      Type: "AWS::Cognito::IdentityPool"
      Properties:
        IdentityPoolName: ${self:custom.appName}_${self:provider.stage}_identity
        CognitoIdentityProviders:
          - ClientId:
              Ref: UserPoolClient

“AWS::Cognito::IdentityPool” 的引用返回此资源的 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
这样做的任何方法?
4个回答

63

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

结合!Sub使用管道符号可以让你轻松地使用:

  • 你的资源Ref返回值,如${YourResource}
  • 它们的Fn::GetAtt返回值只需要用一个句点${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}',
      }

您如何使用JSON来完成同样的事情? - San
@San,您可以使用CloudFormation设计师将YAML和JSON进行转换,详情请参见https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/working-with-templates-cfn-designer-json-editor.html#w2ab1c17c17c13c17c15:只需将模板片段粘贴到上方,然后将“选择模板语言”输入单选按钮从YAML切换到JSON即可。 - Clorichel
1
如果你需要使用!FindInMap怎么办?当'${ var}'只有1行时,我知道可以使用!Sub ['${var}', { var: !FindInMap [...] }]来实现,但是当它是多行时呢? - Matias Haeussler

6

我发现可以使用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来完成此操作。


5
考虑通过更改被接受的答案来给予Clorichel的解决方案认可。 - killthrush

3
使用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",
      }'

3

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

在我的情况下,我使用了多行字符串和!Sub来填充UserData,并在AWS Cloudformation中收到以下错误:

错误:

用户数据的BASE64编码无效。(服务:AmazonEC2;状态代码:400;错误代码:InvalidUserData.Malformed;请求ID:*;代理:null)

解决方案:

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

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接