aws-cloudformation / cloudformation-coverage-roadmap

The AWS CloudFormation Public Coverage Roadmap
https://aws.amazon.com/cloudformation/
Creative Commons Attribution Share Alike 4.0 International
1.11k stars 54 forks source link

New major optional template section - Stack tags #205

Open gwenael-hagenmuller opened 4 years ago

gwenael-hagenmuller commented 4 years ago

1. Title

New major optional template section - Tags

2. Scope of request

A new major (optional) template section which could be called Tags to list the tags to associate with the stack that is created or updated and to propagate to resources in the stack.

This list can already be passed to aws cloudformation deploy through the --tags parameter. See corresponding AWS CLI Command Reference.

That would be in the same idea of the major template section Parameters which allows the user to input custom values to his/her template each time he/she creates or updates a stack. Those parameters can be overridden thanks to the --parameter-overrides parameter of aws cloudformation deploy.

Default values specified in the Tags section of the template should also be overridable thanks to --tags parameter (which should probably be renamed).

Tags:

  Moniker:
    Description: 'Moniker tag'
    Default: 'mycompany:moniker=myservice-myenvironment-awsregion'

  Service:
    Description: 'Service tag'
    Default: 'mycompany:service=myservice-myenvironment-awsregion'

  Environment:
    Description: 'Environment tag'
    Default: 'mycompany:environment=myenvironment'
$ aws cloudformation deploy \
   --tags-overrides \
      Moniker="mycompany:moniker=myservice-DIFFERENTenvironment-awsregion"

It should be possible to reference parameters in the Tags section like it is possible in the Resources section.

Parameters:

  Environment:
    Description: 'Environment in where to deploy the stack'

Tags:

  Environment:
    Description: 'Environment tag'
    Default: !Join ['', ['mycompany:environment=', !Ref 'Environment']]

3. Expected behavior

Tags:

  Moniker:
    Description: 'Moniker tag'
    Default: 'mycompany:moniker=myservice-myenvironment-awsregion'

  Service:
    Description: 'Service tag'
    Default: 'mycompany:service=myservice-myenvironment-awsregion'

  Environment:
    Description: 'Environment tag'
    Default: 'mycompany:environment=myenvironment'

would have the same behavior as:

$ aws cloudformation deploy \
   --tags \
      mycompany:moniker=myservice-myenvironment-awsregion \
      mycompany:service=myservice-myenvironment-awsregion \
      mycompany:environment=myenvironment

4. Category

Other (IoT, Migration, Budgets...)

tkahnoski commented 4 years ago

This would do a lot for tooling. As is we're looking at having to build custom logic around create-stack/update stack to use the --tags argument, but being able to define this as part of the Stack itself would be a massive improvement!

We use tags for limiting team access to things so teams right now can't be granted 'delete stack' permissions in a general way.

benbridts commented 4 years ago

I like this idea a lot, but would like to nitpick some details:

Format

I think it would be best to have to properties, one for Tag Key, an one for Tag Value. Eg:

Tags:
  Moniker:
    Description: 'Moniker tag'
    Key: mycompany:moniker
    Default: 'myservice-myenvironment-awsregion'

References

I can see a value in being able to use an input parameter as a tag, but I see more value the other way around. Another approach might be to work similar to exports and allow the template author to indicate which parameters should also be tags.

Parameters:
  Environment:
    Description: 'Environment in where to deploy the stack'
    TagKey: mycompany:moniker

This leads to some extra advantages where it can follow the exact behaviour regarding overrides as Parameters.

The fact that you cannot use !Refs / !Joins in a description is tracked in aws-cloudformation/cfn-language-discussion#55, adding the same kind of "Tag Export" to the solutions proposed there would address this.

Behaviour

As Parameters

If tags are an extension of parameters, most behaviour is already defined. One thing that needs to be addressed is how to handle possible conflicts with tags from outside the template. I think that making "template tags" behave as read only tags when using the tags apis might be a good solution.

As new section

Updating Tags could work exactly like how tags work right now, with the caveat that it should be impossible to remove tags that are defined in the template. If there will be an "AllowedPattern" for Tags, this should also always be validated.