cfn-language-discussion
cfn-language-discussion copied to clipboard
Support YAML anchors/aliases in CFN yaml templates
Doesn't really fit the issue template, but it would be great if CFN YAML templates would allow to use YAML anchors & aliases.
This way one could simply set an anchor and then refer back to it in other places of the template.
Example (non-cfn - only to demonstrate anchors/aliases)
a: &numbers
- 1
- 2
- 3
b: *numbers
is the same as
a:
- 1
- 2
- 3
b:
- 1
- 2
- 3
Advantages:
- less copy & paste
- less errors when changing a thing (think subnet lists) in one place, but forget to in another
- reusability of computed values (Fn::Join, Fn::Sub, Fn::Cidr)
This would be huge. Not sure why it's not available already.
My use case: I have two stacksets in a parent stack. The stacksets have various configuration properties that should be the same: PermissionModel, AutoDeployment, OperationPreferences, CallAs, Capabilities.
A YAML anchor would be a very simple way to keep this configuration DRY ("don't repeat yourself").
Without an anchor, I think my deduplication options are to use a substack to encapsulate the the common configuration or to generate the deployed template from another source.
In my case I don't want to add that complexity, I really just want to have a single template file (even the stackset template body is defined inline with TemplateBody!).
So for now I have to live with the duplicatation with a comment to the effect of "These settings should be the same for each stack". :smile:
@x6j8x I had the same issue with many services that disallow YAML anchors. I've created the project yarser, a CLI that parses a YAML file that contains anchors to a plain-text YAML file.
Here's how it works:
It is written in Go and based on yq, so the parsing process is quite fast, especially if you use the --watch
mode, where it automatically parses the file on save (like in the demo above).
I know it's not the perfect solution, and it would be better if CloudFormation would support YAML anchors, but until then, you can use yarser.
any update on this?
Maybe a useful note for someone: when using aws cloudformation package
via AWS CLI, it processes the YAML and anchors works just fine.
E.g.:
Resources:
TaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
…
ContainerDefinitions:
- &container
Name: hello-world
Image: hello-world
- <<: *container
Name: ciao-world
Thanks @krystof-k! I'll give it a shot. This could be super helpful!
@x6j8x 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.
+1
+1
Having equivalent support within AWS Step Function state machine definitions as well would be great help to reduce and centralise repetitive configuration. In the config I've tried to deploy just now, using an alias results in SCHEMA_VALIDATION_FAILED
(InvalidDefinition
) errors; anchors seem okay to remain in the YAML but serve no purpose without aliases to reference them.
Maybe a useful note for someone: when using
aws cloudformation package
via AWS CLI, it processes the YAML and anchors works just fine.
@krystof-k you mean that we have to use aws cloudformation package
with --use-json
option:
aws cloudformation package \
--template template.yaml \
--s3-bucket somebucketforcloudformation \
--output-template-file template.json \
--use-json
When converting from YAML to JSON, all anchors and aliases will be resolved.
More info on this workaround: https://medium.com/@rhgvandenheuvel/cloudformation-coding-using-yaml-9127025813bb
But I would prefer this being natively handled by CloudFormation as YAML is more readable than JSON.
@yvele Yes, but you don't have to convert it JSON, it works with YAML too:
aws cloudformation package \
--template-file template.yaml \
--output-template-file packaged-template.yaml \
--s3-bucket bucket
@krystof-k yeah you are right 👍
I'm facing errors because I want to use anchors/aliases within a StackSet template body: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudformation-stackset.html#cfn-cloudformation-stackset-templatebody
StackSet:
Type: AWS::CloudFormation::StackSet
Properties:
TemplateBody: |
Foo: &anchor
- a
- b
Bar: *anchor
and obviously TemplateBody
is a string and anchor/aliases will not be converted within 🤔 I'm a bit stuck
I tried the following:
Transform: AWS::LanguageExtensions
...
StackSet:
Type: AWS::CloudFormation::StackSet
Properties:
TemplateBody: !ToJsonString
Foo: &anchor
- a
- b
Bar: *anchor
It's kind of working.. but the problem with ToJsonString
is that my object will have GetAtt
, etc. being resolved outside the StackSet (resolved from the root document):
Transform: AWS::LanguageExtensions
...
StackSet:
Type: AWS::CloudFormation::StackSet
Properties:
TemplateBody: !ToJsonString
SomeResource:
Type: AWS::SomeResource
Foo: $anchor
- a
- !GetAtt SomeResource.Arn # This will try to find SomeResource in the root document outside the StackSet
Bar: *anchor
Template error: instance of Fn::GetAtt references undefined resource SomeResource
I can't find any workaround to resolve anchors/aliases within a StackSet 🤔
@yvele You are doing it wrong, ~~YAML anchors don't work like that. Try to do it like in my example above.~~ you should use &
instead of $
.
And I think the !ToJsonString function should not matter, because it gets evaluated after the YAML, but I haven't tried that. With the multiline string it won't work.
@yvele You are doing it wrong, ~YAML anchors don't work like that. Try to do it like in my example above.~ you should use
&
instead of$
.
Oops my bad that was a typo only within my response to the thread, I am using &
in my real code.
And I think the
!ToJsonString
function should not matter, because it gets evaluated after the YAML, but I haven't tried that. With the multiline string it won't work.
Hum really with !ToJsonString
I get this error:
Failed to create the changeset: Waiter ChangeSetCreateComplete failed: Waiter encountered a terminal failure state: For expression "Status" we matched expected path: "FAILED" Status: FAILED. Reason: Template error: instance of Fn::GetAtt references undefined resource SomeResource
I don't have the error when I use YAML as plain text but then the StackSet fails during deployment with this error:
Resource handler returned message: "Template error: YAML aliases are not allowed in CloudFormation templates (Service: CloudFormation, Status Code: 400, Request ID: XXX)" (RequestToken: XXX, HandlerErrorCode: GeneralServiceException)
@yvele Yeah, because you are trying to resolve SomeResource
inside !ToJsonString
, that can't work, but that is not related to the YAML anchors.