Repository: NomadBlacky/cdk-datadog-resources (language: python)

Issue:
Support `Datadog::Dashboards::Dashboard` resource
https://github.com/DataDog/datadog-cloudformation-resources/tree/master/datadog-dashboards-dashboard-handler


Discussion / hints:

Fix patch:
diff --git a/API.md b/API.md
index 7727d78..c12592f 100644
--- a/API.md
+++ b/API.md
@@ -4,6 +4,7 @@
 
 Name|Description
 ----|-----------
+[DatadogDashboard](#nomadblacky-cdk-datadog-resources-datadogdashboard)|Datadog Dashboard 1.0.0.
 [DatadogMonitor](#nomadblacky-cdk-datadog-resources-datadogmonitor)|Datadog Monitor 3.0.0.
 
 
@@ -12,6 +13,7 @@ Name|Description
 Name|Description
 ----|-----------
 [DatadogCredentials](#nomadblacky-cdk-datadog-resources-datadogcredentials)|Credentials for the Datadog API.
+[DatadogDashboardProps](#nomadblacky-cdk-datadog-resources-datadogdashboardprops)|*No description*
 [DatadogMonitorProps](#nomadblacky-cdk-datadog-resources-datadogmonitorprops)|*No description*
 [MonitorOptions](#nomadblacky-cdk-datadog-resources-monitoroptions)|*No description*
 [MonitorThresholdWindows](#nomadblacky-cdk-datadog-resources-monitorthresholdwindows)|*No description*
@@ -26,6 +28,29 @@ Name|Description
 
 
 
+## class DatadogDashboard  <a id="nomadblacky-cdk-datadog-resources-datadogdashboard"></a>
+
+Datadog Dashboard 1.0.0.
+
+
+### Initializer
+
+
+
+
+```ts
+new DatadogDashboard(scope: Construct, id: string, props: DatadogDashboardProps)
+```
+
+* **scope** (<code>[Construct](#aws-cdk-core-construct)</code>)  *No description*
+* **id** (<code>string</code>)  *No description*
+* **props** (<code>[DatadogDashboardProps](#nomadblacky-cdk-datadog-resources-datadogdashboardprops)</code>)  *No description*
+  * **dashboardDefinition** (<code>string</code>)  JSON string of the dashboard definition. 
+  * **datadogCredentials** (<code>[DatadogCredentials](#nomadblacky-cdk-datadog-resources-datadogcredentials)</code>)  Credentials for the Datadog API. 
+
+
+
+
 ## class DatadogMonitor  <a id="nomadblacky-cdk-datadog-resources-datadogmonitor"></a>
 
 Datadog Monitor 3.0.0.
@@ -70,6 +95,20 @@ Name | Type | Description
 
 
 
+## struct DatadogDashboardProps  <a id="nomadblacky-cdk-datadog-resources-datadogdashboardprops"></a>
+
+
+
+
+
+
+Name | Type | Description 
+-----|------|-------------
+**dashboardDefinition** | <code>string</code> | JSON string of the dashboard definition.
+**datadogCredentials** | <code>[DatadogCredentials](#nomadblacky-cdk-datadog-resources-datadogcredentials)</code> | Credentials for the Datadog API.
+
+
+
 ## struct DatadogMonitorProps  <a id="nomadblacky-cdk-datadog-resources-datadogmonitorprops"></a>
 
 
diff --git a/README.md b/README.md
index 8c012a0..ae03329 100644
--- a/README.md
+++ b/README.md
@@ -18,9 +18,9 @@ You need to register the correct version listed in `Supported Resources`.
 
 ## Supported Resources
 
-| Supported? | Resource                | Name                             | Description                                              | Datadog CF Version |
+| Supported? | Resource                | Datadog CF Resource Name         | Description                                              | Datadog CF Version |
 | :--------: | ----------------------- | -------------------------------- | -------------------------------------------------------- | ------------------ |
-|            | Dashboards              | `Datadog::Dashboards::Dashboard` | [Create, update, and delete Datadog dashboards.][1]      | N/A                |
+|     ✅     | Dashboards              | `Datadog::Dashboards::Dashboard` | [Create, update, and delete Datadog dashboards.][1]      | [1.0.0][7]         |
 |            | Datadog-AWS integration | `Datadog::Integrations::AWS`     | [Manage your Datadog-Amazon Web Service integration.][2] | N/A                |
 |     ✅     | Monitors                | `Datadog::Monitors::Monitor`     | [Create, update, and delete Datadog monitors.][3]        | [3.0.0][6]         |
 |            | Downtimes               | `Datadog::Monitors::Downtime`    | [Enable or disable downtimes for your monitors.][4]      | N/A                |
@@ -54,19 +54,30 @@ Java
 
 Belows are examples of TypeScript.
 
+### Dashboards
+
+```typescript
+import * as fs from 'fs';
+import { DatadogDashboard } from '@nomadblacky/cdk-datadog-resources';
+
+new DatadogDashboard(yourStack, 'TestDashboard', {
+  datadogCredentials: {
+    apiKey: process.env.DATADOG_API_KEY!,
+    applicationKey: process.env.DATADOG_APP_KEY!,
+  },
+  dashboardDefinition: fs.readFileSync(`${__dirname}/path/to/your/dashboard-definition.json`).toString(),
+});
+```
+
 ### Monitors
 
 ```typescript
-import { App, Stack } from '@aws-cdk/core';
 import { DatadogMonitor } from '@nomadblacky/cdk-datadog-resources';
 
-const app = new App();
-const stack = new Stack(app, 'CdkDatadogResourcesTestStack');
-
-new DatadogMonitor(stack, 'TestMonitor', {
+new DatadogMonitor(yourStack, 'TestMonitor', {
   datadogCredentials: {
-    apiKey: process.env.DATADOG_API_KEY || 'DATADOG_API_KEY',
-    applicationKey: process.env.DATADOG_APP_KEY || 'DATADOG_APP_KEY',
+    apiKey: process.env.DATADOG_API_KEY!,
+    applicationKey: process.env.DATADOG_APP_KEY!,
   },
   query: 'avg(last_1h):sum:system.cpu.system{host:host0} > 100',
   type: MonitorType.QueryAlert,
@@ -89,3 +100,4 @@ new DatadogMonitor(stack, 'TestMonitor', {
 [4]: https://github.com/DataDog/datadog-cloudformation-resources/tree/master/datadog-monitors-downtime-handler
 [5]: https://github.com/DataDog/datadog-cloudformation-resources/tree/master/datadog-iam-user-handler
 [6]: https://github.com/DataDog/datadog-cloudformation-resources/blob/master/datadog-monitors-monitor-handler/CHANGELOG.md#300--2021-02-16
+[7]: https://github.com/DataDog/datadog-cloudformation-resources/blob/master/datadog-dashboards-dashboard-handler/CHANGELOG.md#100--2021-02-16
diff --git a/cf-schema/datadog-dashboard-1.0.0.json b/cf-schema/datadog-dashboard-1.0.0.json
new file mode 100644
index 0000000..a85dda6
--- /dev/null
+++ b/cf-schema/datadog-dashboard-1.0.0.json
@@ -0,0 +1,79 @@
+{
+  "typeName": "Datadog::Dashboards::Dashboard",
+  "description": "Datadog Dashboard 1.0.0",
+  "definitions": {
+  },
+  "properties": {
+    "DatadogCredentials": {
+      "description": "Credentials for the Datadog API",
+      "properties": {
+        "ApiKey": {
+          "description": "Datadog API key",
+          "type": "string"
+        },
+        "ApplicationKey": {
+          "description": "Datadog application key",
+          "type": "string"
+        },
+        "ApiURL": {
+          "description": "Datadog API URL (defaults to https://api.datadoghq.com) Use https://api.datadoghq.eu for EU accounts.",
+          "type": "string"
+        }
+      },
+      "required": [
+        "ApiKey",
+        "ApplicationKey"
+      ],
+      "type": "object"
+    },
+    "Id": {
+      "description": "ID of the dashboard",
+      "type": "string"
+    },
+    "DashboardDefinition": {
+      "description": "JSON string of the dashboard definition",
+      "type": "string"
+    }
+  },
+  "additionalProperties": false,
+  "required": [
+    "DatadogCredentials",
+    "DashboardDefinition"
+  ],
+  "writeOnlyProperties": [
+    "/properties/DatadogCredentials"
+  ],
+  "readOnlyProperties": [
+    "/properties/Id"
+  ],
+  "primaryIdentifier": [
+    "/properties/Id"
+  ],
+  "handlers": {
+    "create": {
+      "permissions": [
+        ""
+      ]
+    },
+    "read": {
+      "permissions": [
+        ""
+      ]
+    },
+    "update": {
+      "permissions": [
+        ""
+      ]
+    },
+    "delete": {
+      "permissions": [
+        ""
+      ]
+    },
+    "list": {
+      "permissions": [
+        ""
+      ]
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/cdk-app.ts b/src/cdk-app.ts
index 77a53af..6f3adac 100644
--- a/src/cdk-app.ts
+++ b/src/cdk-app.ts
@@ -1,15 +1,20 @@
+import * as fs from 'fs';
 import { App, Stack } from '@aws-cdk/core';
+import { DatadogCredentials } from './common/properties';
+import { DatadogDashboard } from './dashboards/datadog-dashboard';
 import { DatadogMonitor } from './monitors/datadog-monitor';
 import { MonitorType } from './monitors/properties';
 
 const app = new App();
 const stack = new Stack(app, 'CdkDatadogResourcesTestStack');
 
+const datadogCredentials: DatadogCredentials = {
+  apiKey: process.env.DATADOG_API_KEY!,
+  applicationKey: process.env.DATADOG_APP_KEY!,
+};
+
 new DatadogMonitor(stack, 'TestMonitor', {
-  datadogCredentials: {
-    apiKey: process.env.DATADOG_API_KEY || 'DATADOG_API_KEY',
-    applicationKey: process.env.DATADOG_APP_KEY || 'DATADOG_APP_KEY',
-  },
+  datadogCredentials,
   query: 'avg(last_1h):sum:system.cpu.system{host:host0} > 100',
   type: MonitorType.QUERY_ALERT,
   name: 'Test Monitor',
@@ -23,3 +28,8 @@ new DatadogMonitor(stack, 'TestMonitor', {
     evaluationDelay: 60,
   },
 });
+
+new DatadogDashboard(stack, 'TestDashboard', {
+  datadogCredentials,
+  dashboardDefinition: fs.readFileSync(`${__dirname}/../test/dashboards/dashboard-def.json`).toString(),
+});
diff --git a/src/common/properties.ts b/src/common/properties.ts
new file mode 100644
index 0000000..21c9da9
--- /dev/null
+++ b/src/common/properties.ts
@@ -0,0 +1,11 @@
+/**
+ * Credentials for the Datadog API
+ */
+export interface DatadogCredentials {
+  /** Datadog API key */
+  readonly apiKey: string;
+  /** Datadog application key */
+  readonly applicationKey: string;
+  /** Datadog API URL (defaults to https://api.datadoghq.com) Use https://api.datadoghq.eu for EU accounts. */
+  readonly apiURL?: string;
+}
diff --git a/src/dashboards/datadog-dashboard.ts b/src/dashboards/datadog-dashboard.ts
new file mode 100644
index 0000000..04d30d2
--- /dev/null
+++ b/src/dashboards/datadog-dashboard.ts
@@ -0,0 +1,27 @@
+import { CfnResource, Construct } from '@aws-cdk/core';
+import * as camelcaseKeys from 'camelcase-keys';
+import { DatadogCredentials } from '../common/properties';
+
+export interface DatadogDashboardProps {
+  /** Credentials for the Datadog API */
+  readonly datadogCredentials: DatadogCredentials;
+
+  /** JSON string of the dashboard definition */
+  readonly dashboardDefinition: string;
+}
+
+/**
+ * Datadog Dashboard 1.0.0
+ */
+export class DatadogDashboard {
+  constructor(scope: Construct, id: string, props: DatadogDashboardProps) {
+    const cfnProperties = camelcaseKeys(props, {
+      deep: true,
+      pascalCase: true,
+    });
+    new CfnResource(scope, id, {
+      type: 'Datadog::Dashboards::Dashboard',
+      properties: { ...cfnProperties },
+    });
+  }
+}
\ No newline at end of file
diff --git a/src/index.ts b/src/index.ts
index 6bdb020..8e6846f 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,2 +1,4 @@
+export * from './common/properties';
 export * from './monitors/datadog-monitor';
 export * from './monitors/properties';
+export * from './dashboards/datadog-dashboard';
diff --git a/src/monitors/datadog-monitor.ts b/src/monitors/datadog-monitor.ts
index 44f190a..c2a2efd 100644
--- a/src/monitors/datadog-monitor.ts
+++ b/src/monitors/datadog-monitor.ts
@@ -1,6 +1,7 @@
 import { CfnResource, Construct } from '@aws-cdk/core';
 import * as camelcaseKeys from 'camelcase-keys';
-import { DatadogCredentials, MonitorOptions, MonitorType } from './properties';
+import { DatadogCredentials } from '../common/properties';
+import { MonitorOptions, MonitorType } from './properties';
 
 export interface DatadogMonitorProps {
   /** Credentials for the Datadog API */
diff --git a/src/monitors/properties.ts b/src/monitors/properties.ts
index b5a5c07..18e4ef2 100644
--- a/src/monitors/properties.ts
+++ b/src/monitors/properties.ts
@@ -1,15 +1,3 @@
-/**
- * Credentials for the Datadog API
- */
-export interface DatadogCredentials {
-  /** Datadog API key */
-  readonly apiKey: string;
-  /** Datadog application key */
-  readonly applicationKey: string;
-  /** Datadog API URL (defaults to https://api.datadoghq.com) Use https://api.datadoghq.eu for EU accounts. */
-  readonly apiURL?: string;
-}
-
 /**
  * The type of the monitor
  */


Test patch:
diff --git a/test/dashboards/__snapshots__/datadog-dashboard.test.ts.snap b/test/dashboards/__snapshots__/datadog-dashboard.test.ts.snap
new file mode 100644
index 0000000..f70b064
--- /dev/null
+++ b/test/dashboards/__snapshots__/datadog-dashboard.test.ts.snap
@@ -0,0 +1,65 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Snapshot test 1`] = `
+Object {
+  "Resources": Object {
+    "TestMonitor": Object {
+      "Properties": Object {
+        "DashboardDefinition": "{
+  \\"title\\": \\"Test from cdk-datadog-resources\\",
+  \\"description\\": \\"\\",
+  \\"widgets\\": [
+    {
+      \\"id\\": 7963397977738346,
+      \\"definition\\": {
+        \\"title\\": \\"\\",
+        \\"title_size\\": \\"16\\",
+        \\"title_align\\": \\"left\\",
+        \\"time\\": {
+
+        },
+        \\"type\\": \\"query_value\\",
+        \\"requests\\": [
+          {
+            \\"q\\": \\"avg:datadog.estimated_usage.hosts{*}\\",
+            \\"aggregator\\": \\"avg\\",
+            \\"conditional_formats\\": [
+              {
+                \\"comparator\\": \\"<=\\",
+                \\"palette\\": \\"white_on_yellow\\",
+                \\"value\\": 0
+              },
+              {
+                \\"comparator\\": \\">=\\",
+                \\"palette\\": \\"white_on_green\\",
+                \\"value\\": 1
+              }
+            ]
+          }
+        ],
+        \\"autoscale\\": true,
+        \\"precision\\": 2
+      }
+    }
+  ],
+  \\"template_variables\\": [
+
+  ],
+  \\"layout_type\\": \\"ordered\\",
+  \\"is_read_only\\": false,
+  \\"notify_list\\": [
+
+  ],
+  \\"id\\": \\"k87-rwz-htu\\"
+}
+",
+        "DatadogCredentials": Object {
+          "ApiKey": "DATADOG_API_KEY",
+          "ApplicationKey": "DATADOG_APP_KEY",
+        },
+      },
+      "Type": "Datadog::Dashboards::Dashboard",
+    },
+  },
+}
+`;
diff --git a/test/dashboards/dashboard-def.json b/test/dashboards/dashboard-def.json
new file mode 100644
index 0000000..b0fe256
--- /dev/null
+++ b/test/dashboards/dashboard-def.json
@@ -0,0 +1,47 @@
+{
+  "title": "Test from cdk-datadog-resources",
+  "description": "",
+  "widgets": [
+    {
+      "id": 7963397977738346,
+      "definition": {
+        "title": "",
+        "title_size": "16",
+        "title_align": "left",
+        "time": {
+
+        },
+        "type": "query_value",
+        "requests": [
+          {
+            "q": "avg:datadog.estimated_usage.hosts{*}",
+            "aggregator": "avg",
+            "conditional_formats": [
+              {
+                "comparator": "<=",
+                "palette": "white_on_yellow",
+                "value": 0
+              },
+              {
+                "comparator": ">=",
+                "palette": "white_on_green",
+                "value": 1
+              }
+            ]
+          }
+        ],
+        "autoscale": true,
+        "precision": 2
+      }
+    }
+  ],
+  "template_variables": [
+
+  ],
+  "layout_type": "ordered",
+  "is_read_only": false,
+  "notify_list": [
+
+  ],
+  "id": "k87-rwz-htu"
+}
diff --git a/test/dashboards/datadog-dashboard.test.ts b/test/dashboards/datadog-dashboard.test.ts
new file mode 100644
index 0000000..1c54aba
--- /dev/null
+++ b/test/dashboards/datadog-dashboard.test.ts
@@ -0,0 +1,20 @@
+import * as fs from 'fs';
+import { SynthUtils } from '@aws-cdk/assert';
+import { Stack } from '@aws-cdk/core';
+import { DatadogDashboard } from '../../src/dashboards/datadog-dashboard';
+
+test('Snapshot test', () => {
+  const stack = new Stack();
+
+  const dashboardDefJson = fs.readFileSync(`${__dirname}/dashboard-def.json`).toString();
+
+  new DatadogDashboard(stack, 'TestMonitor', {
+    datadogCredentials: {
+      apiKey: 'DATADOG_API_KEY',
+      applicationKey: 'DATADOG_APP_KEY',
+    },
+    dashboardDefinition: dashboardDefJson,
+  });
+
+  expect(SynthUtils.toCloudFormation(stack)).toMatchSnapshot();
+});