To create a CloudWatch Dashboard in CloudFormation, you must supply the dashboard's source code as a stringified JSON rather than as a separate JSON structure.
This is annoying because my JSON has to be escaped inside of a string literal within my serverless.yml:
...
resources:
Resources:
MyDashboard:
Type: AWS::CloudWatch::Dashboard
Properties:
DashboardName: My-Dashboard
DashboardBody: "{\"widgets\": [...]}"
I tried using a file reference:
...
resources:
Resources:
MyDashboard:
Type: AWS::CloudWatch::Dashboard
Properties:
DashboardName: My-Dashboard
DashboardBody: ${file(my-dashboard.json)}
but serverless inserts the content as part of the YAML structure, rather than as part of the JSON string:
...
resources:
Resources:
MyDashboard:
Type: AWS::CloudWatch::Dashboard
Properties:
DashboardName: My-Dashboard
DashboardBody:
Widgets:
- ...
- ...
Is there a way to stringify the JSON from my-dashboard.json?
There doesn't appear to be a way stringify JSON directly within a serverless variable. However, you can reference an external .js file, and then stringify the .json file there:
serverless.yml:
...
resources:
Resources:
MyDashboard:
Type: AWS::CloudWatch::Dashboard
Properties:
DashboardName: My-Dashboard
DashboardBody: ${file(my-dashboard-body.js):myDashboardBody}
${file(my-dashboard-body.js):myDashboardBody} is a serverless variable reference. It means that we want to use the value from the myDashboardBody module of the my-dashboard-body.js file.
my-dashboard-body.js:
module.exports.myDashboardBody = (serverless) => {
const fsPromises = require('fs').promises
return fsPromises.readFile('my-dashboard-body.json', 'utf-8')
};
my-dashboard-body.json:
{
"widgets": [
...
]
}