aws-cloudformation / cfn-language-discussion

Language discussions for CloudFormation template language
https://aws.amazon.com/cloudformation/
Apache License 2.0
142 stars 13 forks source link

Map Parameter Type #46

Open josb opened 4 years ago

josb commented 4 years ago

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

...
PatMyron commented 4 years ago

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

benkehoe commented 4 years ago

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.

josb commented 4 years ago

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.

PatMyron commented 4 years ago

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

josb commented 4 years ago

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.

Ricapar commented 4 years ago

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:

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.

jamby1100 commented 4 years ago

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?

josb commented 4 years ago

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 commented 2 years ago

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

lejiati commented 2 years ago

@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.

gbudge commented 11 months ago

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