How dynamically change S3 path inside DefinitionBody

Viewed 149

My code currently is working like this

DefinitionBody:
  'Fn::Transform':
    Name: AWS::Include
    Parameters:
      Location:            
        Fn::Sub: s3://${Bucket}/${AWS::StackName}/${File}
        # Note: Bucket and File comes from Parameters in this case   

Now I try to get {$File} dynamically using FindInMap

    'Fn::Transform':
       Name: AWS::Include
       Parameters:
       Location: !Sub
         - s3://${value-from-parameters-section}/${AWS::StackName}/${spec}
         - { spec: !FindInMap [ "Config", "type", "file"]}

But is throwing me this error:

Failed to digest functions within transform parameters, intrinsic functions in transform block must only contain parameter values or stack metadata

So, How I can achieve to dynamically change the File name inside the DefinitonBody?

2 Answers

You can't do this, it is not supported. AWS docs explicitly states that no intrinsic functions are supported:

Supported functions None. CloudFormation passes any intrinsic function calls included in Fn::Transform to the specified macro as literal strings.

You can re-design your function to use custom resources instead of macros. This way you can do whatever you wish.

In this case, I think the message is self-explanatory

Failed to digest functions within transform parameters, intrinsic functions in transform block must only contain parameter values or stack metadata

Only metadata or parameters are allowed, that is the reason this works

DefinitionBody:
  'Fn::Transform':
  Name: AWS::Include
  Parameters:
    Location:            
      Fn::Sub: s3://${Bucket}/${AWS::StackName}/${StackType}

In case somebody needs a workaround I just remove the mapping section and rename the name of the files to match the type I want, something like this

Parameters:
  StackType:
    Type: String
    AllowedValues:
      - typeA
      - typeB
  Bucket:
    Type: String

Then I just use this sub to get the DefinitionBody like this:

DefinitionBody:
    'Fn::Transform':
      Name: AWS::Include
      Parameters:
        Location:
          Fn::Sub: s3://${Bucket}/${AWS::StackName}/${StackType}-API.yaml

This will resolve like this:

s3://example-bucket/name-of-stack/typeA-API.yaml 
or
s3://example-bucket/name-of-stack/typeB-API.yaml

So now I just need to have these files named in that way on the S3, this is similar to what mapping should do, but for now, is not supported, this will achieve what I want, is not perfect but did the trick, still remain the confusion because I think the documentation is inaccurate

Related