Skip to content

Commit 6702691

Browse files
author
ljacobsson
committed
Fix for #25 🎉
1 parent 5422ad5 commit 6702691

File tree

9 files changed

+62
-40
lines changed

9 files changed

+62
-40
lines changed

.vscode/launch.json

Lines changed: 0 additions & 25 deletions
This file was deleted.

README.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,24 @@ Html Options:
3939
## Output formats
4040

4141
### Draw.io
42+
```
43+
Usage: cfn-dia draw.io|d [options]
44+
45+
Generates a draw.io diagram from a CloudFormation template
46+
47+
Options:
48+
-t, --template-file [templateFile] Path to template or cdk.json file (default: "template.yaml or
49+
cdk.json")
50+
-c, --ci-mode Disable terminal/console interactivity (default: false)
51+
--stacks [stacks] Comma separated list of stack name(s) to include. Defaults to
52+
all.
53+
-o, --output-file [outputFile] Name of output file (default: "template.drawio")
54+
-co, --cdk-output [outputPath] CDK synth output path (default: "cdk.out")
55+
-s, --skip-synth Skips CDK synth (default: false)
56+
-e, --exclude-types [excludeTypes...] List of resource types to exclude when using CI mode
57+
-h, --help display help for command
58+
```
59+
4260
Use it in combination with the [Draw.io Integration](https://marketplace.visualstudio.com/items?itemName=hediet.vscode-drawio) for VS Code to instantly visualise your stacks.
4361

4462
![Demo](https://raw.githubusercontent.com/mhlabs/cfn-diagram/master/demo.gif)
@@ -56,6 +74,24 @@ cfn-dia draw.io -t template.yaml
5674
* Works with CloudFormation, SAM and CDK
5775

5876
### HTML
77+
```
78+
Usage: cfn-dia html|h [options]
79+
80+
Generates a vis.js diagram from a CloudFormation template
81+
82+
Options:
83+
-t, --template-file [templateFile] Path to template or cdk.json file (default: "template.yaml or
84+
cdk.json")
85+
--stacks [stacks] Comma separated list of stack name(s) to include. Defaults to all.
86+
-all --render-all If set, all nested stacks will be rendered. By default only root
87+
template is rendered (default: false)
88+
-c, --ci-mode Disable terminal/console interactivity (default: false)
89+
-o, --output-path [outputPath] Name of output file (default: "/tmp/cfn-diagram")
90+
-co, --cdk-output [outputPath] CDK synth output path (default: "cdk.out")
91+
-s, --skip-synth Skips CDK synth (default: false)
92+
-h, --help display help for command
93+
```
94+
5995
The HTML output uses [vis.js](https://github.com/visjs/vis-network) to generate an interactive diagram from your template.
6096

6197
![Demo](https://raw.githubusercontent.com/mhlabs/cfn-diagram/master/demo-html.gif)
@@ -69,6 +105,8 @@ or, for CDK stacks, go to project directory (where cdk.json is located) and ente
69105
cfn-dia html
70106
```
71107

108+
Large stacks, in particular multi-stack CDK projects, tend to generate huge diagrams. You can pass the stack names you want to render using the `--stacks` argument followed by a comma separated list of stack names.
109+
72110
### CI-mode
73111
This functionality lives in its own CLI, [cfn-diagram-ci](https://github.com/mhlabs/cfn-diagram-ci). This is beacuse it requires headless Chromium to be installed which makes the package size very large
74112

commands/draw.io/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ program
1616
"Disable terminal/console interactivity",
1717
false
1818
)
19+
.option("--stacks [stacks]", "Comma separated list of stack name(s) to include. Defaults to all.")
1920
.option("-o, --output-file [outputFile]", "Name of output file", "template.drawio")
2021
.option(
2122
"-co, --cdk-output [outputPath]",

commands/html/index.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ program
1313
"Path to template or cdk.json file",
1414
"template.yaml or cdk.json"
1515
)
16+
.option("--stacks [stacks]", "Comma separated list of stack name(s) to include. Defaults to all.")
17+
.option("-all --render-all", "If set, all nested stacks will be rendered. By default only root template is rendered", false)
1618
.option("-c, --ci-mode", "Disable terminal/console interactivity", false)
1719
.option(
1820
"-o, --output-path [outputPath]",
@@ -29,6 +31,8 @@ program
2931
templateObj.template,
3032
template.isJson,
3133
cmd.outputPath,
32-
ciMode
34+
ciMode,
35+
false,
36+
cmd.renderAll
3337
);
3438
});

graph/Vis.js

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ function reset() {
2424
types = new Set();
2525
}
2626

27-
function makeGraph(template, prefix, doReset) {
27+
function makeGraph(template, prefix, doReset, renderAll) {
2828
if (doReset) {
2929
reset();
3030
}
@@ -38,15 +38,16 @@ function makeGraph(template, prefix, doReset) {
3838
types.add(type);
3939
if (resObj.Template) {
4040
nested.push(resource);
41-
makeGraph(resObj.Template, resource);
41+
makeGraph(resObj.Template, resource, false, renderAll);
4242
}
4343
const dependencies = getDependencies(template, resource);
4444
addnodes(
4545
resource,
4646
dependencies,
4747
type,
4848
template.Resources[resource],
49-
prefix
49+
prefix,
50+
renderAll
5051
);
5152
}
5253

@@ -106,14 +107,14 @@ function addEdges(from, to, dependencyNode, fromNode) {
106107
}
107108
}
108109

109-
function addnodes(resource, dependencies, type, resourceObject, prefix) {
110+
function addnodes(resource, dependencies, type, resourceObject, prefix, renderAll) {
110111
delete resourceObject.Template;
111112
if (nodes.filter((p) => p.id === resource).length === 0) {
112113
nodes.push({
113114
id: `${prefix}.${resource}`,
114115
dependencies: dependencies,
115116
prefix: prefix,
116-
hidden: prefix != "root",
117+
hidden: prefix != "root" && !renderAll,
117118
type: type,
118119
label: resource,
119120
shape: "image",
@@ -162,11 +163,11 @@ function getDependencies(template, resource) {
162163
return dependencies;
163164
}
164165

165-
async function renderTemplate(template, isJson, filePath, ciMode, reset) {
166+
async function renderTemplate(template, isJson, filePath, ciMode, reset, renderAll) {
166167
useJson = isJson;
167-
const { nodes, edges } = makeGraph(template, "root", reset);
168+
const { nodes, edges } = makeGraph(template, "root", reset, renderAll);
168169
const fileContent = `
169-
170+
var renderAll = ${renderAll}
170171
var nodes = new vis.DataSet(${JSON.stringify(nodes)});
171172
var edges = new vis.DataSet(${JSON.stringify(edges)});
172173
var nested = ${JSON.stringify(nested.sort())};

graph/ui/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@
143143
if (!showSidebar) {
144144
document.getElementById("filtersContainer").hidden = true;
145145
}
146-
populateFilters("nested-stacks", nested, false, (x) => {
146+
populateFilters("nested-stacks", nested, renderAll, (x) => {
147147
const ns = nodes.get({ filter: (p) => p.prefix === x.target.value });
148148
for (const n of ns) {
149149
nodes.update({ id: n.id, hidden: !x.target.checked });

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@mhlabs/cfn-diagram",
3-
"version": "1.1.25",
3+
"version": "1.1.26",
44
"description": "CLI tool to visualise CloudFormation, SAM or CDK stacks as draw.io or HTML diagrams",
55
"main": "index.js",
66
"scripts": {

resources/JsonUtil.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,13 +80,12 @@ function findAllValues(obj, keyArray, keyName, path) {
8080
}
8181
values = multiValue.map((p) => p[0]);
8282
}
83-
8483
if (prop === "Fn::ImportValue") {
8584
const split = typeof values[0] ==="string" && values[0].split(":");
8685
if (split.length == 2) {
8786
const stackName = split[0];
8887
const exportName = split[1];
89-
const value = templateCache.templates[stackName].Outputs[exportName].Value;
88+
const value = templateCache.templates[stackName] ? templateCache.templates[stackName].Outputs[exportName].Value : {"Fn::ImportValue": "Unknown"};
9089
const intrinsicFunction = Object.keys(value)[0];
9190
const prefix = stackName === templateCache.rootTemplate ? "root" : stackName;
9291
values[0] = `${prefix}.${value[intrinsicFunction]}`;

shared/templateParser.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,16 +77,20 @@ function fromCDK(cmd) {
7777
if (!cmd.skipSynth) {
7878
cp.execSync("cdk synth -o " + cmd.cdkOutput);
7979
}
80+
const manifestFile = fs.readFileSync(path.join(cmd.cdkOutput, "manifest.json"));
8081
const treeFile = fs.readFileSync(path.join(cmd.cdkOutput, "tree.json"));
82+
const manifest = JSON.parse(manifestFile);
8183
const tree = JSON.parse(treeFile);
82-
const stacks = Object.keys(tree.tree.children).filter((p) => p !== "Tree");
83-
const parentStack = stacks.shift();
84+
const includeStacks = cmd.stacks ? cmd.stacks.split(",").map(p=>p.trim()) : null;
85+
let stacks = Object.keys(manifest.artifacts).filter((p) => p !== "Tree" && (!includeStacks || includeStacks.includes(p)));
86+
const parentStack = Object.keys(tree.tree.children).filter((p) => p !== "Tree" && (!includeStacks || includeStacks.includes(p)))[0];
8487
const template = fs.readFileSync(
8588
path.join(cmd.cdkOutput, `${parentStack}.template.json`)
8689
);
8790
const parsedTemplate = JSON.parse(template);
8891
templateCache.templates[parentStack] = parsedTemplate;
8992
templateCache.rootTemplate = parentStack;
93+
stacks = stacks.filter(p => p != parentStack);
9094
for (const stack of stacks) {
9195
const childTemplate = fs.readFileSync(
9296
path.join(cmd.cdkOutput, `${stack}.template.json`)

0 commit comments

Comments
 (0)