Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC 0014: New Intrinsic Function to Convert Template Block to JSON String #15

Closed
wants to merge 4 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 124 additions & 0 deletions RFCs/0014-ToJsonString.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
# New Intrinsic Function to Convert Template Block to JSON String

* **Original Author(s):**: @mluk-aws
* **Tracking Issue**: [Tracking Issue](https://github.com/aws-cloudformation/cfn-language-discussion/issues/14)

# Summary

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\"}"
jlhood marked this conversation as resolved.
Show resolved Hide resolved
}
}
```

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:
jlhood marked this conversation as resolved.
Show resolved Hide resolved
password: "Pa$$word"
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`.
jlhood marked this conversation as resolved.
Show resolved Hide resolved

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

# 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).
jlhood marked this conversation as resolved.
Show resolved Hide resolved
jlhood marked this conversation as resolved.
Show resolved Hide resolved
* 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?
* 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" }
}
]
}
}
}
}
}
}
```