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

Parameter extensions / Parameter types for resource types.

Open benbridts opened this issue 3 years ago • 5 comments

Name of the resource

Other

Resource name

No response

Description

Currently CloudFormation supports a limited list of AWS-specific parameter types. It would be a very useful to have parameter types for:

  • every resource type that implements a List handler
  • private parameter types

It could even go a step further and resolv attributes of those resources

Examples:

# Returns the primary identifier
Type: AWS::CloudFormation::Stack::$id
# Selection options for multiple primary identifiers
Type: List<AWS::CloudFormation::Stack::$id>
# Using a private resource type
Type: Type: MyCompany::Service::Product::$id
# Returns the !GetAtt StackSetId of the selected resource (selection still via primary identifier)
# Note: this might be confusing, but querying all Attributes seems unfeasable
Type: AWS::CloudFormation::StackSet::StackSetId
Type: List<AWS::CloudFormation::StackSet::StackSetId>

Of course alternative syntax is also possible. Eg.

# primary identifiers
Type: CloudControl<AWS::CloudFormation::Stack>
Type: CloudControlList<AWS::CloudFormation::Stack>
# GetAtt
Type: CloudControlAttribute<AWS::CloudFormation::StackSet, StackSetId>
Type: CloudControlAttributeList<AWS::CloudFormation::StackSet, StackSetId>

Other Details

This is probably extra powerful when used in Service Catalog

benbridts avatar Oct 20 '21 08:10 benbridts

I don't think this should require types that implement list handlers, nor should it need a specification of a property within a resource type. The parameter type should just be the resource type itself and the input value required in the stack operation is the primary identifier as defined in the schema, and then the input name is referenceable like a normal resource. The list handler, if it's defined, is used by the AWS console to provide a dropdown of primary identifiers.

The template would look like:

Parameters:
  Role:
    Type: AWS::IAM::Role
Resources:
  Function:
    Type: AWS::Lambda::Function
    Properties:
      Role: !GetAtt Role.Arn
      # etc

and then CreateStack requires a role ARN as a parameter value.

Same with lists of types, e.g. List<AWS::IAM::Role>; a syntax for referencing resources within the list could be common with the Fn::Map proposal in aws-cloudformation/cfn-language-discussion#41.

benkehoe avatar Oct 20 '21 14:10 benkehoe

parameter type should just be the resource type itself and the input value required in the stack operation is the primary identifier as defined in the schema, and then the input name is referenceable like a normal resource

I think that's a great idea.

The only use case that neither of our proposals captures is specifying a resource by a non-primary identifier. I didn't include it, because that wouldn't work with the List handler output. If you're skipping that (and rely on the read handler only), it would be nice to be able to do this:

Parameters:
  TopicName:
    Type: AWS::SNS::Topic
    AllowedPattern: `[A-Za-z0-9]+` # The read handler will also throw an error if the resource does not exist
    ConstraintDescription: Please only specify the name, not the full ARN
    # a more generic "ResourceTransform" might also be useful for resources that don't expect an arn, 
    # but where you want the parameter to be one - although that is tricky if a cross-region ARN is pasted
    ResourceSub: "arn:${AWS::Partition}:sns:${AWS::Region}:${AWS::AccountId}:${TopicName}" 

There are some places where you can't do this (eg. you need an extra id for AWS::CloudFormation::Stack), but other resources might benefit from this, so that either all parameters are ARNs, or none of them are.


Side note on the ResourceTransform and specifying the wrong region: A ResourceMatch could help with that, where it would throw a validationError if the values do not match:

Parameters:
  RoleArn:
    Type: AWS::Lambda::Function
    # this will extract the Name to be used as identifier
    # and throw an error if we're not matching regions/accounts
    ResourceMatch: arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:([a-zA-Z0-9-_]+).*

benbridts avatar Oct 20 '21 15:10 benbridts

The only use case that neither of our proposals captures is specifying a resource by a non-primary identifier.

I think this would be something the UI would handle, because you have to pick which non-primary identifier you'd specify by, and then it could issue a read call to get the primary identifier.

Or it could be a part of the stack operation that you can either specific the parameter value as a string, or as an object with the non-primary identifier property name and value.

benkehoe avatar Oct 20 '21 15:10 benkehoe

In an ideal world, it would. Most resources schemas don't specify additional identifiers, even if they exists, though.

benbridts avatar Oct 20 '21 15:10 benbridts

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