From 231d15b74026fe1e8d1f1f162f07fab9738df52b Mon Sep 17 00:00:00 2001 From: Michael Luk Date: Fri, 29 Apr 2022 15:26:08 -0700 Subject: [PATCH 1/4] Adding Fn::ToJsonString RFC --- RFCs/0014-ToJsonString.md | 108 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 RFCs/0014-ToJsonString.md diff --git a/RFCs/0014-ToJsonString.md b/RFCs/0014-ToJsonString.md new file mode 100644 index 0000000..455d213 --- /dev/null +++ b/RFCs/0014-ToJsonString.md @@ -0,0 +1,108 @@ +# New Intrinsic Function to Convert Template Block to JSON String + +* **Original Author(s):**: @michaluk +* **Tracking Issue**: [Tracking Issue](https://github.com/aws-cloudformation/cfn-language-discussion/issues/14) +* **Reviewer**: @cfn-language-and-tools-team + +# Summary + +As part of Language Extensions, we will support an intrinsic function called `Fn::ToJsonString` that enables developers to convert a template block into an escaped JSON string, which can be used as input values to string-type properties of CloudFormation resources. + +# Examples + +Here is an example of a resource containing a string-type property using a JSON formatted string. +``` +"MySecret": { + "Type": "AWS::SecretsManager::Secret", + "Properties": { + "Name": "MySecret", + "SecretString": "{\"password\":\"Pa$$word\",\"secretToken\":\"123\"}" + } +} +``` + +With the new `Fn::ToJsonString` intrinsic function we can simplify to the following: + +## JSON +``` +"MySecret": { + "Type": "AWS::SecretsManager::Secret", + "Properties": { + "Name": "MySecret", + "SecretString": { + "Fn::ToJsonString": { + "password":"Pa$$word", + "secretToken": "123" + } + } + } +} +``` + +## YAML +``` +MySecret: + Type: AWS::SecretsManager::Secret + Properties: + Name: MySecret + SecretString: + Fn::ToJsonString: + password: "Pa$$word" + secretToken: "123" +``` + +# Motivation + +A CloudFormation user may want to use JSON strings as input to a resource property. For example, `AWS::CloudWatch::Dashboard` requires a JSON string for the `DashboardBody` attribute. A user may even want to use a JSON string as input to attributes where only a general string is required, such as in `SecretString` of `AWS::SecretsManager::Secret`. + +Today, this can only be accomplished through the use of external tools to convert object bodies to JSON strings, or use workarounds such as YAML multiline syntax. Having a feature to automate this transformation can provide various benefits, such as improving development workflow, improving code readability, or being able to utilize JSON/YAML syntax highlighting in text editors. + +Open Github request regarding this: https://github.com/aws-cloudformation/cloudformation-coverage-roadmap/issues/78 + +# Limitation + +YAML is a superset of JSON, so there are a few features in YAML that can not be converted to JSON due to their differences. For example, comments are supported in YAML but not JSON. This can potentially be a confusing developer experience if the developer is not aware of these limitations and have different expectations. + +# Details + +`Fn::ToJsonString` is an intrinsic function that takes in a template block as input and converts it into an escaped JSON string. + +* It will be restricted to only be used as the value of string-type resource properties. +* Intrinsic functions (e.g. `Fn::If`, `Ref`) or pseudo parameters (e.g. `AWS::NoValue`) can be used within the input template block, with the limitation that references can not be made to resource properties. The input template block will be processed by the intrinsic functions and pseudo parameters before it is converted to a string (i.e. the resolved value of the intrinsic function is converted to the output string, and not the intrinsic function itself). +* Conversion will always retain the same order of key-value pairs such that the converted strings of the same input template block are guaranteed to not change. + +# FAQ +* Will the CloudFormation Linter (cfn-lint) support validations regarding Fn::ToJsonString? + * Yes. It needs to validate that it’s only used for string-type resource properties, and that the input template block is valid. + +# Appendix +Example of a full template utilizing `Fn::ToJsonString`: +``` +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "Example dashboard template", + "Resources": { + "MyDashboard": { + "Type": "AWS::CloudWatch::Dashboard", + "Properties": { + "DashboardBody": { + "Fn::ToJsonString": { + "start": "-PT6H", + "periodOverride": "inherit", + "widgets": [ + { + "type": "text", + "x": 0, + "y": 7, + "width": 3, + "height": 3, + "properties": { "markdown": "Hello world" } + } + ] + } + } + } + } + } +} +``` \ No newline at end of file From a8489048236435edec609b5b32077a3142f2beb0 Mon Sep 17 00:00:00 2001 From: Michael Luk Date: Tue, 3 May 2022 11:38:45 -0700 Subject: [PATCH 2/4] Updating to correct Original Author of ToJsonString RFC --- RFCs/0014-ToJsonString.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RFCs/0014-ToJsonString.md b/RFCs/0014-ToJsonString.md index 455d213..c47d10e 100644 --- a/RFCs/0014-ToJsonString.md +++ b/RFCs/0014-ToJsonString.md @@ -1,6 +1,6 @@ # New Intrinsic Function to Convert Template Block to JSON String -* **Original Author(s):**: @michaluk +* **Original Author(s):**: @mluk-aws * **Tracking Issue**: [Tracking Issue](https://github.com/aws-cloudformation/cfn-language-discussion/issues/14) * **Reviewer**: @cfn-language-and-tools-team From 20d7085c2e144bf9f90ad25586607ec0be457913 Mon Sep 17 00:00:00 2001 From: Michael Luk Date: Tue, 3 May 2022 16:47:49 -0700 Subject: [PATCH 3/4] Updating ToJsonString RFC with additional detail --- RFCs/0014-ToJsonString.md | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/RFCs/0014-ToJsonString.md b/RFCs/0014-ToJsonString.md index c47d10e..fdf5742 100644 --- a/RFCs/0014-ToJsonString.md +++ b/RFCs/0014-ToJsonString.md @@ -51,6 +51,18 @@ MySecret: secretToken: "123" ``` +### Short Form Syntax +``` +MySecret: + Type: AWS::SecretsManager::Secret + Properties: + Name: MySecret + SecretString: + !ToJsonString: + password: "Pa$$word" + secretToken: "123" +``` + # Motivation A CloudFormation user may want to use JSON strings as input to a resource property. For example, `AWS::CloudWatch::Dashboard` requires a JSON string for the `DashboardBody` attribute. A user may even want to use a JSON string as input to attributes where only a general string is required, such as in `SecretString` of `AWS::SecretsManager::Secret`. @@ -59,10 +71,6 @@ Today, this can only be accomplished through the use of external tools to conver Open Github request regarding this: https://github.com/aws-cloudformation/cloudformation-coverage-roadmap/issues/78 -# Limitation - -YAML is a superset of JSON, so there are a few features in YAML that can not be converted to JSON due to their differences. For example, comments are supported in YAML but not JSON. This can potentially be a confusing developer experience if the developer is not aware of these limitations and have different expectations. - # Details `Fn::ToJsonString` is an intrinsic function that takes in a template block as input and converts it into an escaped JSON string. @@ -70,6 +78,14 @@ YAML is a superset of JSON, so there are a few features in YAML that can not be * It will be restricted to only be used as the value of string-type resource properties. * Intrinsic functions (e.g. `Fn::If`, `Ref`) or pseudo parameters (e.g. `AWS::NoValue`) can be used within the input template block, with the limitation that references can not be made to resource properties. The input template block will be processed by the intrinsic functions and pseudo parameters before it is converted to a string (i.e. the resolved value of the intrinsic function is converted to the output string, and not the intrinsic function itself). * Conversion will always retain the same order of key-value pairs such that the converted strings of the same input template block are guaranteed to not change. +* The following pseudo parameters will be supported: + * `AWS::AccountId`, `AWS::Region`, `AWS::Partition`, `AWS::NoValue` + +# Limitation + +* YAML is a superset of JSON, so there are a few features in YAML that can not be converted to JSON due to their differences. For example, comments are supported in YAML but not JSON. This can potentially be a confusing developer experience if the developer is not aware of these limitations and have different expectations. +* Unsupported pseudo parameters: + * `AWS::StackId`, `AWS::StackName`, `AWS::NotificationArns`, `AWS::URLSuffix` # FAQ * Will the CloudFormation Linter (cfn-lint) support validations regarding Fn::ToJsonString? @@ -105,4 +121,5 @@ Example of a full template utilizing `Fn::ToJsonString`: } } } -``` \ No newline at end of file +``` + From 4a9148c11cf0796ac469e6a2f68c2f1447e86f2f Mon Sep 17 00:00:00 2001 From: Michael Luk Date: Fri, 6 May 2022 16:15:21 -0700 Subject: [PATCH 4/4] Revising ToJsonString RFC --- RFCs/0014-ToJsonString.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/RFCs/0014-ToJsonString.md b/RFCs/0014-ToJsonString.md index fdf5742..3e73682 100644 --- a/RFCs/0014-ToJsonString.md +++ b/RFCs/0014-ToJsonString.md @@ -2,11 +2,10 @@ * **Original Author(s):**: @mluk-aws * **Tracking Issue**: [Tracking Issue](https://github.com/aws-cloudformation/cfn-language-discussion/issues/14) -* **Reviewer**: @cfn-language-and-tools-team # Summary -As part of Language Extensions, we will support an intrinsic function called `Fn::ToJsonString` that enables developers to convert a template block into an escaped JSON string, which can be used as input values to string-type properties of CloudFormation resources. +We will support an intrinsic function called `Fn::ToJsonString` that enables developers to convert a template block into an escaped JSON string, which can be used as input values to string-type properties of CloudFormation resources. # Examples