cfn-language-discussion icon indicating copy to clipboard operation
cfn-language-discussion copied to clipboard

Map Parameter Type

Open josb opened this issue 4 years ago • 11 comments

Given the 60 parameter template limit, structured parameters are a way to overcome this limitation. Example:

Parameters:
  LogGroupInfo:
    Type: Map

...

Resources
...

  CloudWatchLogsGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !GetAtt LogGroupInfo.Name
      RetentionInDays: !GetAtt LogGroupInfo.RetentionInDays

...

josb avatar Jul 27 '20 23:07 josb

Would simply raising the parameter limit be better? Raising that limit is currently being investigated

PatMyron avatar Jul 28 '20 19:07 PatMyron

I don't see this as a workaround; resources have structured parameters, and with nested stacks, stacks can be resources, so they should also have structured parameters.

benkehoe avatar Jul 28 '20 19:07 benkehoe

Additionally, a Map parameter type would help organize the stack parameter space. Traditionally, the example above would be implemented using two parameters, and some form of parameter prefix convention would be used to organize the names to indicate that they are related to the same resource. This imposes additional cognitive burden on humans, especially when many parameters are present. The same issue applies to outputs - instead of multiple related outputs, a single structured output could be used.

josb avatar Jul 28 '20 22:07 josb

Got it. There's also AWS::CloudFormation::Interface which can help organize stack parameters a bit if using the console to input parameter values if that helps your use-case at all

PatMyron avatar Jul 28 '20 22:07 PatMyron

I'm aware of AWS::CloudFormation::Interface, but our use case has hundreds of CloudFormation stacks per deployment and is largely driven by extensive custom automation code. And because we are running into the 60-parameter limit, we had to resort to using parameter stacks just for the purpose of working around that limit. We do use the CloudFormation console, but mostly for debugging. For reasons stated above, with 700+ parameters per deployment, a Map-type parameter would help us organize this better.

josb avatar Jul 28 '20 23:07 josb

I think raising the parameter limit would certainly be something that would help in @josb's use case, but I would say that even without that scenario the overall CloudFormation developer community stands to benefit greatly from a hash/dictionary parameter type.

As an example, for a stack that perhaps creates two AWS::EC2::Instances, quite often I find myself generating parameters like this:

  • Instance1Type
  • Instance1VolumeSize
  • Instance1SecurityGroup
  • Instance2Type
  • Instance2VolumeSize
  • Instance2SecurityGroup

And if I suddenly need to make a 3rd instance as part of the stack or perhaps need a 4th parameter then that suddenly adds a lot more parameters.

With a hash/dict parameter type, even though I'd be passing the same amount of information, it would be a whole lot cleaner and easier to read and understand.

Ricapar avatar Jul 29 '20 14:07 Ricapar

A workaround that has worked for me is using the PyPlate CloudFormation macro. Create the macro first by creating a CF stack using that template.

First, create a CommaDelimitedList parameter in your template:

Transform: [PyPlate]
Parameters:
  AutoScalingContainerCountRange:
    Description: The min and max number of containers
    Type: CommaDelimitedList
    Default: MinCapacity=2,MaxCapacity=5

Then, in your template, you can reference Python code to do parsing. I loop through the list and split it by "=" to separate key and value:

Resources:
  AutoScalingTarget:
    Type: AWS::ApplicationAutoScaling::ScalableTarget
    Properties:
      MinCapacity: |
        #!PyPlate
        autoscale_range_dict = {}
        for alarm_param in params['AutoScalingContainerCountRange']:
          condition,value = alarm_param.split('=')
          autoscale_range_dict[condition] = value
        output = int(autoscale_range_dict['MinCapacity'])

This is not the most elegant solution since I had to use a macro. But it allows me to create key-value pairs like MinCapacity=2,MaxCapacity=5. I still support this feature request though! Adding a "Hash" parameter would make my templates cleaner since I don't have to add Python code inside my templates.

How about you guys, how did you work around this?

jamby1100 avatar Aug 09 '20 04:08 jamby1100

Thanks for sharing this, @jamby1100. We have similar macros that operate on CommaDelimitedLists, including the use of inline Ruby ERB templating. And surely others have come up with similar solutions as workarounds. But they increase cognitive load for people dealing with the code, and add to the maintenance burden. A centralized solution offered by AWS would avoid all these duplicative efforts.

josb avatar Aug 10 '20 18:08 josb

Changed from Hash to Map as the latter is what YAML calls this key-value data structure.

josb avatar Apr 27 '22 19:04 josb

@josb Thank you very much for your feedback! Since this repository is focused on resource coverage, I'm transferring this issue over to a new GitHub repository dedicated to CloudFormation template language issues.

lejiati avatar May 10 '22 02:05 lejiati

Is this one going anywhere? I could certainly use this.

gbudge avatar Oct 11 '23 09:10 gbudge