Skip to content

Commit 3b070e5

Browse files
committed
feat: JSON output
This adds the JSON output on top of #221, which can be enabled by passing `--output json`. Internally it works exactly the same as the `template` output format with the default template. ``` ******************** Release was not present in Helm. Diff will show entire contents as new. ******************** [{ "api": "v1", "kind": "Secret", "namespace": "default", "name": "mysql-1567775891", "change": "ADD" },{ "api": "v1", "kind": "ConfigMap", "namespace": "default", "name": "mysql-1567775891-test", "change": "ADD" },{ "api": "v1", "kind": "PersistentVolumeClaim", "namespace": "default", "name": "mysql-1567775891", "change": "ADD" },{ "api": "v1", "kind": "Service", "namespace": "default", "name": "mysql-1567775891", "change": "ADD" },{ "api": "apps", "kind": "Deployment", "namespace": "default", "name": "mysql-1567775891", "change": "ADD" }] ``` Ref #221 (review)
1 parent 20028d2 commit 3b070e5

File tree

4 files changed

+78
-57
lines changed

4 files changed

+78
-57
lines changed

Makefile

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ PKG:= github.com/databus23/helm-diff
55
LDFLAGS := -X $(PKG)/cmd.Version=$(VERSION)
66

77
# Clear the "unreleased" string in BuildMetadata
8-
LDFLAGS += -X $(PKG)/vendor/k8s.io/helm/pkg/version.BuildMetadata=
9-
LDFLAGS += -X $(PKG)/vendor/k8s.io/helm/pkg/version.Version=$(shell grep -A1 "package: k8s.io/helm" go.mod | sed -n -e 's/[ ]*version:.*\(v[.0-9]*\).*/\1/p')
8+
LDFLAGS += -X k8s.io/helm/pkg/version.BuildMetadata=
9+
LDFLAGS += -X k8s.io/helm/pkg/version.Version=$(shell ./scripts/dep-helm-version.sh)
1010

1111
.PHONY: format
1212
format:
13-
test -z "$$(find . -path ./vendor -prune -type f -o -name '*.go' -exec gofmt -d {} + | tee /dev/stderr)" || \
14-
test -z "$$(find . -path ./vendor -prune -type f -o -name '*.go' -exec gofmt -w {} + | tee /dev/stderr)"
13+
test -z "$$(find . -type f -o -name '*.go' -exec gofmt -d {} + | tee /dev/stderr)" || \
14+
test -z "$$(find . -type f -o -name '*.go' -exec gofmt -w {} + | tee /dev/stderr)"
1515

1616
.PHONY: install
1717
install: build

cmd/upgrade.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ func newChartCommand() *cobra.Command {
112112
f.IntVarP(&diff.outputContext, "context", "C", -1, "output NUM lines of context around changes")
113113
f.BoolVar(&diff.disableOpenAPIValidation, "disable-openapi-validation", false, "disables rendered templates validation against the Kubernetes OpenAPI Schema")
114114
f.StringVar(&diff.postRenderer, "post-renderer", "", "the path to an executable to be used for post rendering. If it exists in $PATH, the binary will be used, otherwise it will try to look for the executable at the given path")
115-
f.StringVar(&diff.output, "output", "diff", "Possible values: diff, simple, template. When set to \"template\", use the env var HELM_DIFF_TPL to specify the template.")
115+
f.StringVar(&diff.output, "output", "diff", "Possible values: diff, simple, json, template. When set to \"template\", use the env var HELM_DIFF_TPL to specify the template.")
116116
if !isHelm3() {
117117
f.StringVar(&diff.namespace, "namespace", "default", "namespace to assume the release to be installed into")
118118
}

diff/constant.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@ const defaultTemplateReport = `[
44
{{- $global := . -}}
55
{{- range $idx, $entry := . -}}
66
{
7-
"Api": "{{ $entry.API }}",
8-
"Kind": "{{ $entry.Kind }}",
9-
"Namespace": "{{ $entry.Namespace }}",
10-
"Name": "{{ $entry.Name }}",
11-
"Change": "{{ $entry.Change }}"
7+
"api": "{{ $entry.API }}",
8+
"kind": "{{ $entry.Kind }}",
9+
"namespace": "{{ $entry.Namespace }}",
10+
"name": "{{ $entry.Name }}",
11+
"change": "{{ $entry.Change }}"
1212
}{{ if not (last $idx $global) }},{{ end }}
13-
{{- end }}]`
13+
{{- end }}]
14+
`

diff/report.go

Lines changed: 66 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ type ReportEntry struct {
3333

3434
// ReportFormat to the context to make a changes report
3535
type ReportFormat struct {
36-
output string
36+
output func(r *Report, to io.Writer)
3737
changestyles map[string]ChangeStyle
3838
}
3939

@@ -61,6 +61,8 @@ func (r *Report) setupReportFormat(format string) {
6161
setupSimpleReport(&report)
6262
case "template":
6363
setupTemplateReport(&report)
64+
case "json":
65+
setupJSONReport(&report)
6466
default:
6567
setupDiffReport(&report)
6668
}
@@ -81,14 +83,7 @@ func (r *Report) addEntry(key string, suppressedKinds []string, kind string, con
8183

8284
// print: prints entries added to the report.
8385
func (r *Report) print(to io.Writer) {
84-
switch r.format.output {
85-
case "simple":
86-
printSimpleReport(r, to)
87-
case "template":
88-
printTemplateReport(r, to)
89-
default:
90-
printDiffReport(r, to)
91-
}
86+
r.format.output(r, to)
9287
}
9388

9489
// clean: needed for testing
@@ -98,7 +93,7 @@ func (r *Report) clean() {
9893

9994
// setup report for default output: diff
10095
func setupDiffReport(r *Report) {
101-
r.format.output = "diff"
96+
r.format.output = printDiffReport
10297
r.format.changestyles = make(map[string]ChangeStyle)
10398
r.format.changestyles["ADD"] = ChangeStyle{color: "green", message: "has been added:"}
10499
r.format.changestyles["REMOVE"] = ChangeStyle{color: "red", message: "has been removed:"}
@@ -116,7 +111,7 @@ func printDiffReport(r *Report, to io.Writer) {
116111

117112
// setup report for simple output.
118113
func setupSimpleReport(r *Report) {
119-
r.format.output = "simple"
114+
r.format.output = printSimpleReport
120115
r.format.changestyles = make(map[string]ChangeStyle)
121116
r.format.changestyles["ADD"] = ChangeStyle{color: "green", message: "to be added."}
122117
r.format.changestyles["REMOVE"] = ChangeStyle{color: "red", message: "to be removed."}
@@ -140,9 +135,55 @@ func printSimpleReport(r *Report, to io.Writer) {
140135
fmt.Fprintf(to, "Plan: %d to add, %d to change, %d to destroy.\n", summary["ADD"], summary["MODIFY"], summary["REMOVE"])
141136
}
142137

138+
func newTemplate(name string) *template.Template {
139+
// Prepare template functions
140+
var funcsMap = template.FuncMap{
141+
"last": func(x int, a interface{}) bool {
142+
return x == reflect.ValueOf(a).Len()-1
143+
},
144+
}
145+
146+
return template.New(name).Funcs(funcsMap)
147+
}
148+
149+
// setup report for json output
150+
func setupJSONReport(r *Report) {
151+
t, err := newTemplate("entries").Parse(defaultTemplateReport)
152+
if err != nil {
153+
log.Fatalf("Error loadding default template: %v", err)
154+
}
155+
156+
r.format.output = templateReportPrinter(t)
157+
r.format.changestyles = make(map[string]ChangeStyle)
158+
r.format.changestyles["ADD"] = ChangeStyle{color: "green", message: ""}
159+
r.format.changestyles["REMOVE"] = ChangeStyle{color: "red", message: ""}
160+
r.format.changestyles["MODIFY"] = ChangeStyle{color: "yellow", message: ""}
161+
}
162+
143163
// setup report for template output
144164
func setupTemplateReport(r *Report) {
145-
r.format.output = "template"
165+
var tpl *template.Template
166+
167+
{
168+
tplFile, present := os.LookupEnv("HELM_DIFF_TPL")
169+
if present {
170+
t, err := newTemplate(filepath.Base(tplFile)).ParseFiles(tplFile)
171+
if err != nil {
172+
fmt.Println(err)
173+
log.Fatalf("Error loadding custom template")
174+
}
175+
tpl = t
176+
} else {
177+
// Render
178+
t, err := newTemplate("entries").Parse(defaultTemplateReport)
179+
if err != nil {
180+
log.Fatalf("Error loadding default template")
181+
}
182+
tpl = t
183+
}
184+
}
185+
186+
r.format.output = templateReportPrinter(tpl)
146187
r.format.changestyles = make(map[string]ChangeStyle)
147188
r.format.changestyles["ADD"] = ChangeStyle{color: "green", message: ""}
148189
r.format.changestyles["REMOVE"] = ChangeStyle{color: "red", message: ""}
@@ -165,42 +206,21 @@ func (t *ReportTemplateSpec) loadFromKey(key string) error {
165206
}
166207

167208
// load and print report for template output
168-
func printTemplateReport(r *Report, to io.Writer) {
169-
var templateDataArray []ReportTemplateSpec
170-
171-
for _, entry := range r.entries {
172-
templateData := ReportTemplateSpec{}
173-
err := templateData.loadFromKey(entry.key)
174-
if err != nil {
175-
log.Println("error processing report entry")
176-
} else {
177-
templateData.Change = entry.changeType
178-
templateDataArray = append(templateDataArray, templateData)
209+
func templateReportPrinter(t *template.Template) func(r *Report, to io.Writer) {
210+
return func(r *Report, to io.Writer) {
211+
var templateDataArray []ReportTemplateSpec
212+
213+
for _, entry := range r.entries {
214+
templateData := ReportTemplateSpec{}
215+
err := templateData.loadFromKey(entry.key)
216+
if err != nil {
217+
log.Println("error processing report entry")
218+
} else {
219+
templateData.Change = entry.changeType
220+
templateDataArray = append(templateDataArray, templateData)
221+
}
179222
}
180-
}
181223

182-
// Prepare template functions
183-
var funcsMap = template.FuncMap{
184-
"last": func(x int, a interface{}) bool {
185-
return x == reflect.ValueOf(a).Len()-1
186-
},
187-
}
188-
189-
tplFile, present := os.LookupEnv("HELM_DIFF_TPL")
190-
if present {
191-
t, err := template.New(filepath.Base(tplFile)).Funcs(funcsMap).ParseFiles(tplFile)
192-
if err != nil {
193-
fmt.Println(err)
194-
log.Fatalf("Error loadding custom template")
195-
}
196224
t.Execute(to, templateDataArray)
197-
} else {
198-
// Render
199-
t, err := template.New("entries").Funcs(funcsMap).Parse(defaultTemplateReport)
200-
if err != nil {
201-
log.Fatalf("Error loadding default template")
202-
} else {
203-
t.Execute(to, templateDataArray)
204-
}
205225
}
206226
}

0 commit comments

Comments
 (0)