Skip to content

Commit c447ded

Browse files
authored
support -html flag to render output as HTML (#70)
* support `-html` flag to render output as HTML This addresses issue #69 to support HTML output. This also... - updates the README usage docs - validates that multiple, conflicting format flags are not provided - fixes a bug in the tests to properly validate expected tf-summarize errors Signed-off-by: Mike Ball <mikedball@gmail.com> * improve tests to exercise outputs Previously, the tf-summarize tests did not exercise the tool's ability to summarize plan outputs. This fixes that! * ensure 'make help' outputs details on all targets By adding a code comment in association with all Make targets, `make help` now documents all targets: ``` $ make help build build the binary example generate example Terraform plan help prints help (only for tasks with comment) i build and install to /usr/local/bin/ install build and install to /usr/local/bin/ lint lint source code test go test ``` * put HTML resources in <code> within summary This makes the HTML output a bit more consistent with output elsewhere. * protecting against stale tests runs This protects against false positives running the tests. --------- Signed-off-by: Mike Ball <mikedball@gmail.com>
1 parent 2c17fcc commit c447ded

File tree

17 files changed

+231
-34
lines changed

17 files changed

+231
-34
lines changed

Makefile

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
TERRAFORM_VERSION:=$(shell cat example/.terraform-version)
22

3+
define generate-example
4+
docker run \
5+
--interactive \
6+
--tty \
7+
--volume $(shell pwd):/src \
8+
--workdir /src/example \
9+
--entrypoint /bin/sh \
10+
hashicorp/terraform:$(1) \
11+
-c \
12+
"terraform init && \
13+
terraform plan -out tfplan && \
14+
terraform show -json tfplan > tfplan.json"
15+
endef
16+
317
.PHONY: help
418
help: ## prints help (only for tasks with comment)
519
@grep -E '^[a-zA-Z._-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
@@ -13,28 +27,14 @@ build: ## build the binary
1327
install: build ## build and install to /usr/local/bin/
1428
cp $(EXECUTABLE_NAME) /usr/local/bin/$(EXECUTABLE_NAME)
1529

16-
test: lint
17-
go test ./...
30+
test: lint ## go test
31+
go test ./... -count=1
1832

1933
i: install ## build and install to /usr/local/bin/
2034

21-
lint:
35+
lint: ## lint source code
2236
golangci-lint run --timeout 10m -v
2337

24-
define generate-example
25-
docker run \
26-
--interactive \
27-
--tty \
28-
--volume $(shell pwd):/src \
29-
--workdir /src/example \
30-
--entrypoint /bin/sh \
31-
hashicorp/terraform:$(1) \
32-
-c \
33-
"terraform init && \
34-
terraform plan -out tfplan && \
35-
terraform show -json tfplan > tfplan.json"
36-
endef
37-
38-
example:
38+
example: ## generate example Terraform plan
3939
$(call generate-example,$(TERRAFORM_VERSION))
4040
.PHONY: example

README.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,16 @@ Usage of tf-summarize [args] [tf-plan.json|tfplan]
110110
111111
-draw
112112
[Optional, used only with -tree or -separate-tree] draw trees instead of plain tree
113+
-html
114+
[Optional] print changes in html format
115+
-json
116+
[Optional] print changes in json format
117+
-md
118+
[Optional, used only with table view] output table as markdown
113119
-out string
114120
[Optional] write output to file
115121
-separate-tree
116-
[Optional] print changes in tree format for each add/delete/change/recreate changes
122+
[Optional] print changes in tree format for add/delete/change/recreate changes
117123
-tree
118124
[Optional] print changes in tree format
119125
-v print version

example/.terraform.lock.hcl

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

example/github/main.tf

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,8 @@ resource "github_branch" "main" {
2020
resource "github_branch" "development" {
2121
repository = github_repository.repository.name
2222
branch = "development"
23-
}
23+
}
24+
25+
output "repository_name" {
26+
value = github_repository.repository.name
27+
}

example/main.tf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,7 @@ resource "github_repository" "terraform_plan_summary" {
5858
has_wiki = true
5959
vulnerability_alerts = false
6060
}
61+
62+
output "terraform_plan_summary_repository_name" {
63+
value = github_repository.terraform_plan_summary.name
64+
}

example/tfplan.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

main.go

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ func main() {
1818
printVersion := flag.Bool("v", false, "print version")
1919
tree := flag.Bool("tree", false, "[Optional] print changes in tree format")
2020
json := flag.Bool("json", false, "[Optional] print changes in json format")
21+
html := flag.Bool("html", false, "[Optional] print changes in html format")
2122
separateTree := flag.Bool("separate-tree", false, "[Optional] print changes in tree format for add/delete/change/recreate changes")
2223
drawable := flag.Bool("draw", false, "[Optional, used only with -tree or -separate-tree] draw trees instead of plain tree")
2324
md := flag.Bool("md", false, "[Optional, used only with table view] output table as markdown")
@@ -35,7 +36,7 @@ func main() {
3536
}
3637

3738
args := flag.Args()
38-
err := validateFlags(*tree, *separateTree, *drawable, *md, args)
39+
err := validateFlags(*tree, *separateTree, *drawable, *md, *json, *html, args)
3940
logIfErrorAndExit("invalid input flags: %s\n", err, flag.Usage)
4041

4142
newReader, err := reader.CreateReader(args)
@@ -52,7 +53,7 @@ func main() {
5253

5354
terraformstate.FilterNoOpResources(&terraformState)
5455

55-
newWriter := writer.CreateWriter(*tree, *separateTree, *drawable, *md, *json, terraformState)
56+
newWriter := writer.CreateWriter(*tree, *separateTree, *drawable, *md, *json, *html, terraformState)
5657

5758
var outputFile io.Writer = os.Stdout
5859

@@ -83,7 +84,7 @@ func logIfErrorAndExit(format string, err error, callback func()) {
8384
}
8485
}
8586

86-
func validateFlags(tree, separateTree, drawable bool, md bool, args []string) error {
87+
func validateFlags(tree, separateTree, drawable bool, md bool, json bool, html bool, args []string) error {
8788
if tree && md {
8889
return fmt.Errorf("both -tree and -md should not be provided")
8990
}
@@ -96,8 +97,23 @@ func validateFlags(tree, separateTree, drawable bool, md bool, args []string) er
9697
if !tree && !separateTree && drawable {
9798
return fmt.Errorf("drawable should be provided with -tree or -seperate-tree")
9899
}
100+
if multipleTrueVals(md, json, html) {
101+
return fmt.Errorf("only one of -md, -json, or -html should be provided")
102+
}
99103
if len(args) > 1 {
100104
return fmt.Errorf("only one argument is allowed which is filename, but got %v", args)
101105
}
102106
return nil
103107
}
108+
109+
func multipleTrueVals(vals ...bool) bool {
110+
v := []bool{}
111+
112+
for _, val := range vals {
113+
if val {
114+
v = append(v, val)
115+
}
116+
}
117+
118+
return len(v) > 1
119+
}

main_test.go

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,20 @@ func TestTFSummarize(t *testing.T) {
6161
}, {
6262
command: fmt.Sprintf("cat example/tfplan.json | ./%s -md", testExecutable),
6363
expectedOutput: "basic.txt",
64+
}, {
65+
command: fmt.Sprintf("cat example/tfplan.json | ./%s -html", testExecutable),
66+
expectedOutput: "basic.html",
67+
}, {
68+
command: fmt.Sprintf("cat example/tfplan.json | ./%s -md -html", testExecutable),
69+
expectedError: fmt.Errorf("exit status 1"),
70+
expectedOutput: "multiple_format_flags_error.txt",
6471
}}
6572

6673
for _, test := range tests {
6774
t.Run(fmt.Sprintf("when tf-summarize is passed '%q'", test.command), func(t *testing.T) {
68-
output, err := exec.Command("/bin/sh", "-c", test.command).CombinedOutput()
69-
if err != nil && test.expectedError == nil {
70-
t.Errorf("expected '%s' not to error; got '%v'", test.command, err)
75+
output, cmdErr := exec.Command("/bin/sh", "-c", test.command).CombinedOutput()
76+
if cmdErr != nil && test.expectedError == nil {
77+
t.Errorf("expected '%s' not to error; got '%v'", test.command, cmdErr)
7178
}
7279

7380
b, err := os.ReadFile(fmt.Sprintf("testdata/%s", test.expectedOutput))
@@ -77,12 +84,12 @@ func TestTFSummarize(t *testing.T) {
7784

7885
expected := string(b)
7986

80-
if test.expectedError != nil && err == nil {
81-
t.Errorf("expected error '%s'; got '%v'", test.expectedError.Error(), err)
87+
if test.expectedError != nil && cmdErr == nil {
88+
t.Errorf("expected error '%s'; got '%v'", test.expectedError.Error(), cmdErr)
8289
}
8390

84-
if test.expectedError != nil && err != nil && test.expectedError.Error() != err.Error() {
85-
t.Errorf("expected error '%s'; got '%v'", test.expectedError.Error(), err.Error())
91+
if test.expectedError != nil && cmdErr != nil && test.expectedError.Error() != cmdErr.Error() {
92+
t.Errorf("expected error '%s'; got '%v'", test.expectedError.Error(), cmdErr.Error())
8693
}
8794

8895
if string(output) != expected {

testdata/basic.html

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<table>
2+
<tr>
3+
<th>CHANGE</th>
4+
<th>RESOURCE</th>
5+
</tr>
6+
<tr>
7+
<td>add</td>
8+
<td>
9+
<ul>
10+
<li><code>github_repository.terraform_plan_summary</code></li>
11+
<li><code>module.github["demo-repository"].github_branch.development</code></li>
12+
<li><code>module.github["demo-repository"].github_branch.main</code></li>
13+
<li><code>module.github["demo-repository"].github_repository.repository</code></li>
14+
<li><code>module.github["terraform-plan-summary"].github_branch.development</code></li>
15+
<li><code>module.github["terraform-plan-summary"].github_branch.main</code></li>
16+
<li><code>module.github["terraform-plan-summary"].github_repository.repository</code></li>
17+
</ul>
18+
</td>
19+
</tr>
20+
</table>
21+
<table>
22+
<tr>
23+
<th>CHANGE</th>
24+
<th>OUTPUT</th>
25+
</tr>
26+
<tr>
27+
<td>add</td>
28+
<td>
29+
<ul>
30+
<li><code>terraform_plan_summary_repository_name</code></li>
31+
</ul>
32+
</td>
33+
</tr>
34+
</table>

testdata/basic.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,7 @@
77
| | `module.github["terraform-plan-summary"].github_branch.development` |
88
| | `module.github["terraform-plan-summary"].github_branch.main` |
99
| | `module.github["terraform-plan-summary"].github_repository.repository` |
10+
11+
| CHANGE | OUTPUT |
12+
|--------|------------------------------------------|
13+
| add | `terraform_plan_summary_repository_name` |

0 commit comments

Comments
 (0)