CloudFormation ForEach OutputKey processing

0

We have the following CloudFormation template that creates subscriptions from one SQS queue to one or more SNS topics. We need it to be dynamic since we don't know how many topics we will have beforehand.

...
Transform: "AWS::LanguageExtensions"

Parameters:
  TopicNames:
    Type: CommaDelimitedList
    Description: A list of SNS topic Names.
  QueueArn:
    Type: String
    Description: QueueArn.

Resources:
  Fn::ForEach::Subscription:
    - TopicName
    - !Ref TopicNames
    - !Join [ "", !Split [ "-", !Sub "SnsSubscription${TopicName}" ] ]:
        Type: AWS::SNS::Subscription
        Properties:
          Protocol: sqs
          Endpoint: !Ref QueueArn
          Region: !Ref "AWS::Region"
          TopicArn: !Sub "arn:aws:sns:${AWS::Region}:${AWS::AccountId}:${TopicName}"

The problem is that the topic names will contain hyphens, so we cannot just use SnsSubscription${TopicName} in the ForEach OutputKey (because Resource Logical IDs have to be alphanumeric).

The Split-Join strategy used in the snippet above fails with Error creating stack: An error occurred (ValidationError) when calling the CreateStack operation: Template format error: [/Resources/Fn::ForEach::Subscription/2] map keys must be strings; received a map instead. Join returns a string, as far as I know, I guess it has to do with how ForEach preprocesses this input.

Any idea on how to solve this? Is developing a custom macro our only option?

Thanks!

4개 답변
0

As far as I know, Fn::Join returns a string. After playing around with this for a bit, I was able to get an example working:

AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::LanguageExtensions'
Parameters:
  QueueNames:
    Type: CommaDelimitedList
    Description: A list of SNS topic Names.
    Default: 'queue-1, queue-2, queue-3'
Resources:
  Fn::ForEach::Subscription:
    - QueueName
    - !Split [",", !Join ["", !Split ["-", !Join [",", !Split [", ", !Ref QueueNames]]]]]
    - "${QueueName}":
        Type: AWS::SQS::Queue
        Properties: 
          QueueName: !Sub "${QueueName}"

I am not sure what your topic names look like (other than having a dash in them), but this should be enough to get you where you need to go. The issue with the old template is that, as far as I can tell, you cannot use intrinsic functions for the "output key."

답변함 7달 전
0

Hi Dylan, thanks for your answer.

The problem with that solution, in our case, is that we also need the original TopicName (including hyphens and/or whatever other non-alphanumeric character) to build the TopicArn for the subscription (check the last line of the template snippet).

As you say, looks like just a "plain" string is allowed for the OutputKey.

답변함 7달 전
0

The same problem with Fn::ForEach in CloudFormation. Anyone can help? Thank you.

HuanNV
답변함 7달 전
0

Try this:

Transform: "AWS::LanguageExtensions"

Parameters:
  TopicNames:
    Type: CommaDelimitedList
    Description: A list of SNS topic Names.
  QueueArn:
    Type: String
    Description: QueueArn.

Resources:
  Fn::ForEach::Subscription:
    - TopicName
    - !Ref TopicNames
    - "SnsSubscription&{TopicName}":
        Type: AWS::SNS::Subscription
        Properties:
          Protocol: sqs
          Endpoint: !Ref QueueArn
          Region: !Ref "AWS::Region"
          TopicArn: !Sub "arn:aws:sns:${AWS::Region}:${AWS::AccountId}:${TopicName}"

From docs:

OutputKey The key in the transformed template. ${Identifier} or &{Identifier} must be included within the OutputKey parameter. For example, if Fn::ForEach is used in the Resources section of the template, this is the logical Id of each resource.

The &{} syntax allows non-alphanumeric characters in the Collection to be used in OutputKey parameter.

답변함 4달 전

로그인하지 않았습니다. 로그인해야 답변을 게시할 수 있습니다.

좋은 답변은 질문에 명확하게 답하고 건설적인 피드백을 제공하며 질문자의 전문적인 성장을 장려합니다.

질문 답변하기에 대한 가이드라인

관련 콘텐츠