Skip to content

Add support for custom output formats #221

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions cmd/release.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type release struct {
outputContext int
includeTests bool
showSecrets bool
output string
}

const releaseCmdLongUsage = `
Expand Down Expand Up @@ -77,6 +78,8 @@ func releaseCmd() *cobra.Command {
releaseCmd.Flags().StringArrayVar(&diff.suppressedKinds, "suppress", []string{}, "allows suppression of the values listed in the diff output")
releaseCmd.Flags().IntVarP(&diff.outputContext, "context", "C", -1, "output NUM lines of context around changes")
releaseCmd.Flags().BoolVar(&diff.includeTests, "include-tests", false, "enable the diffing of the helm test hooks")
releaseCmd.Flags().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.")

releaseCmd.SuggestionsMinimumDistance = 1

if !isHelm3() {
Expand Down Expand Up @@ -117,6 +120,7 @@ func (d *release) differentiateHelm3() error {
d.suppressedKinds,
d.showSecrets,
d.outputContext,
d.output,
os.Stdout)

if d.detailedExitCode && seenAnyChanges {
Expand Down Expand Up @@ -150,6 +154,7 @@ func (d *release) differentiate() error {
d.suppressedKinds,
d.showSecrets,
d.outputContext,
d.output,
os.Stdout)

if d.detailedExitCode && seenAnyChanges {
Expand Down
7 changes: 7 additions & 0 deletions cmd/revision.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type revision struct {
outputContext int
includeTests bool
showSecrets bool
output string
}

const revisionCmdLongUsage = `
Expand Down Expand Up @@ -87,6 +88,8 @@ func revisionCmd() *cobra.Command {
revisionCmd.Flags().StringArrayVar(&diff.suppressedKinds, "suppress", []string{}, "allows suppression of the values listed in the diff output")
revisionCmd.Flags().IntVarP(&diff.outputContext, "context", "C", -1, "output NUM lines of context around changes")
revisionCmd.Flags().BoolVar(&diff.includeTests, "include-tests", false, "enable the diffing of the helm test hooks")
revisionCmd.Flags().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.")

revisionCmd.SuggestionsMinimumDistance = 1

if !isHelm3() {
Expand Down Expand Up @@ -122,6 +125,7 @@ func (d *revision) differentiateHelm3() error {
d.suppressedKinds,
d.showSecrets,
d.outputContext,
d.output,
os.Stdout)

case 2:
Expand All @@ -147,6 +151,7 @@ func (d *revision) differentiateHelm3() error {
d.suppressedKinds,
d.showSecrets,
d.outputContext,
d.output,
os.Stdout)

if d.detailedExitCode && seenAnyChanges {
Expand Down Expand Up @@ -185,6 +190,7 @@ func (d *revision) differentiate() error {
d.suppressedKinds,
d.showSecrets,
d.outputContext,
d.output,
os.Stdout)

case 2:
Expand All @@ -210,6 +216,7 @@ func (d *revision) differentiate() error {
d.suppressedKinds,
d.showSecrets,
d.outputContext,
d.output,
os.Stdout)

if d.detailedExitCode && seenAnyChanges {
Expand Down
5 changes: 5 additions & 0 deletions cmd/rollback.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type rollback struct {
outputContext int
includeTests bool
showSecrets bool
output string
}

const rollbackCmdLongUsage = `
Expand Down Expand Up @@ -79,6 +80,8 @@ func rollbackCmd() *cobra.Command {
rollbackCmd.Flags().StringArrayVar(&diff.suppressedKinds, "suppress", []string{}, "allows suppression of the values listed in the diff output")
rollbackCmd.Flags().IntVarP(&diff.outputContext, "context", "C", -1, "output NUM lines of context around changes")
rollbackCmd.Flags().BoolVar(&diff.includeTests, "include-tests", false, "enable the diffing of the helm test hooks")
rollbackCmd.Flags().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.")

rollbackCmd.SuggestionsMinimumDistance = 1

if !isHelm3() {
Expand Down Expand Up @@ -115,6 +118,7 @@ func (d *rollback) backcastHelm3() error {
d.suppressedKinds,
d.showSecrets,
d.outputContext,
d.output,
os.Stdout)

if d.detailedExitCode && seenAnyChanges {
Expand Down Expand Up @@ -150,6 +154,7 @@ func (d *rollback) backcast() error {
d.suppressedKinds,
d.showSecrets,
d.outputContext,
d.output,
os.Stdout)

if d.detailedExitCode && seenAnyChanges {
Expand Down
7 changes: 4 additions & 3 deletions cmd/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ type diffCmd struct {
outputContext int
showSecrets bool
postRenderer string
output string
install bool
}

Expand Down Expand Up @@ -111,6 +112,7 @@ func newChartCommand() *cobra.Command {
f.IntVarP(&diff.outputContext, "context", "C", -1, "output NUM lines of context around changes")
f.BoolVar(&diff.disableOpenAPIValidation, "disable-openapi-validation", false, "disables rendered templates validation against the Kubernetes OpenAPI Schema")
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")
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.")
if !isHelm3() {
f.StringVar(&diff.namespace, "namespace", "default", "namespace to assume the release to be installed into")
}
Expand Down Expand Up @@ -171,8 +173,7 @@ func (d *diffCmd) runHelm3() error {
} else {
newSpecs = manifest.Parse(string(installManifest), d.namespace, helm3TestHook, helm2TestSuccessHook)
}

seenAnyChanges := diff.Manifests(currentSpecs, newSpecs, d.suppressedKinds, d.showSecrets, d.outputContext, os.Stdout)
seenAnyChanges := diff.Manifests(currentSpecs, newSpecs, d.suppressedKinds, d.showSecrets, d.outputContext, d.output, os.Stdout)

if d.detailedExitCode && seenAnyChanges {
return Error{
Expand Down Expand Up @@ -258,7 +259,7 @@ func (d *diffCmd) run() error {
}
}

seenAnyChanges := diff.Manifests(currentSpecs, newSpecs, d.suppressedKinds, d.showSecrets, d.outputContext, os.Stdout)
seenAnyChanges := diff.Manifests(currentSpecs, newSpecs, d.suppressedKinds, d.showSecrets, d.outputContext, d.output, os.Stdout)

if d.detailedExitCode && seenAnyChanges {
return Error{
Expand Down
13 changes: 13 additions & 0 deletions diff/constant.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package diff

const defaultTemplateReport = `[
{{- $global := . -}}
{{- range $idx, $entry := . -}}
{
"Api": "{{ $entry.API }}",
"Kind": "{{ $entry.Kind }}",
"Namespace": "{{ $entry.Namespace }}",
"Name": "{{ $entry.Name }}",
"Change": "{{ $entry.Change }}"
}{{ if not (last $idx $global) }},{{ end }}
{{- end }}]`
18 changes: 9 additions & 9 deletions diff/diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ import (
)

// Manifests diff on manifests
func Manifests(oldIndex, newIndex map[string]*manifest.MappingResult, suppressedKinds []string, showSecrets bool, context int, to io.Writer) bool {
func Manifests(oldIndex, newIndex map[string]*manifest.MappingResult, suppressedKinds []string, showSecrets bool, context int, output string, to io.Writer) bool {
report.setupReportFormat(output)
seenAnyChanges := false
emptyMapping := &manifest.MappingResult{}
for key, oldContent := range oldIndex {
if newContent, ok := newIndex[key]; ok {
if oldContent.Content != newContent.Content {
// modified
fmt.Fprintf(to, ansi.Color("%s has changed:", "yellow")+"\n", key)
if !showSecrets {
redactSecrets(oldContent, newContent)
}
Expand All @@ -35,11 +35,10 @@ func Manifests(oldIndex, newIndex map[string]*manifest.MappingResult, suppressed
if len(diffs) > 0 {
seenAnyChanges = true
}
printDiffRecords(suppressedKinds, oldContent.Kind, context, diffs, to)
report.addEntry(key, suppressedKinds, oldContent.Kind, context, diffs, "MODIFY")
}
} else {
// removed
fmt.Fprintf(to, ansi.Color("%s has been removed:", "yellow")+"\n", key)
if !showSecrets {
redactSecrets(oldContent, nil)

Expand All @@ -48,24 +47,25 @@ func Manifests(oldIndex, newIndex map[string]*manifest.MappingResult, suppressed
if len(diffs) > 0 {
seenAnyChanges = true
}
printDiffRecords(suppressedKinds, oldContent.Kind, context, diffs, to)
report.addEntry(key, suppressedKinds, oldContent.Kind, context, diffs, "REMOVE")
}
}

for key, newContent := range newIndex {
if _, ok := oldIndex[key]; !ok {
// added
fmt.Fprintf(to, ansi.Color("%s has been added:", "yellow")+"\n", key)
if !showSecrets {
redactSecrets(nil, newContent)
}
diffs := diffMappingResults(emptyMapping, newContent)
if len(diffs) > 0 {
seenAnyChanges = true
}
printDiffRecords(suppressedKinds, newContent.Kind, context, diffs, to)
report.addEntry(key, suppressedKinds, newContent.Kind, context, diffs, "ADD")
}
}
report.print(to)
report.clean()
return seenAnyChanges
}

Expand Down Expand Up @@ -138,10 +138,10 @@ func getComment(s string) string {
}

// Releases reindex the content based on the template names and pass it to Manifests
func Releases(oldIndex, newIndex map[string]*manifest.MappingResult, suppressedKinds []string, showSecrets bool, context int, to io.Writer) bool {
func Releases(oldIndex, newIndex map[string]*manifest.MappingResult, suppressedKinds []string, showSecrets bool, context int, output string, to io.Writer) bool {
oldIndex = reIndexForRelease(oldIndex)
newIndex = reIndexForRelease(newIndex)
return Manifests(oldIndex, newIndex, suppressedKinds, showSecrets, context, to)
return Manifests(oldIndex, newIndex, suppressedKinds, showSecrets, context, output, to)
}

func diffMappingResults(oldContent *manifest.MappingResult, newContent *manifest.MappingResult) []difflib.DiffRecord {
Expand Down
65 changes: 63 additions & 2 deletions diff/diff_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package diff

import (
"bytes"
"os"
"testing"

"github.com/mgutz/ansi"
Expand Down Expand Up @@ -158,7 +159,7 @@ metadata:

var buf1 bytes.Buffer

if changesSeen := Manifests(specBeta, specRelease, []string{}, true, 10, &buf1); !changesSeen {
if changesSeen := Manifests(specBeta, specRelease, []string{}, true, 10, "diff", &buf1); !changesSeen {
t.Error("Unexpected return value from Manifests: Expected the return value to be `true` to indicate that it has seen any change(s), but was `false`")
}

Expand All @@ -176,10 +177,70 @@ metadata:
t.Run("OnNoChange", func(t *testing.T) {
var buf2 bytes.Buffer

if changesSeen := Manifests(specRelease, specRelease, []string{}, true, 10, &buf2); changesSeen {
if changesSeen := Manifests(specRelease, specRelease, []string{}, true, 10, "diff", &buf2); changesSeen {
t.Error("Unexpected return value from Manifests: Expected the return value to be `false` to indicate that it has NOT seen any change(s), but was `true`")
}

require.Equal(t, ``, buf2.String())
})

t.Run("OnChangeSimple", func(t *testing.T) {

var buf1 bytes.Buffer

if changesSeen := Manifests(specBeta, specRelease, []string{}, true, 10, "simple", &buf1); !changesSeen {
t.Error("Unexpected return value from Manifests: Expected the return value to be `true` to indicate that it has seen any change(s), but was `false`")
}

require.Equal(t, `default, nginx, Deployment (apps) to be changed.
Plan: 0 to add, 1 to change, 0 to destroy.
`, buf1.String())
})

t.Run("OnNoChangeSimple", func(t *testing.T) {
var buf2 bytes.Buffer

if changesSeen := Manifests(specRelease, specRelease, []string{}, true, 10, "simple", &buf2); changesSeen {
t.Error("Unexpected return value from Manifests: Expected the return value to be `false` to indicate that it has NOT seen any change(s), but was `true`")
}

require.Equal(t, "Plan: 0 to add, 0 to change, 0 to destroy.\n", buf2.String())
})

t.Run("OnChangeTemplate", func(t *testing.T) {

var buf1 bytes.Buffer

if changesSeen := Manifests(specBeta, specRelease, []string{}, true, 10, "template", &buf1); !changesSeen {
t.Error("Unexpected return value from Manifests: Expected the return value to be `true` to indicate that it has seen any change(s), but was `false`")
}

require.Equal(t, `[{
"Api": "apps",
"Kind": "Deployment",
"Namespace": "default",
"Name": "nginx",
"Change": "MODIFY"
}]`, buf1.String())
})

t.Run("OnNoChangeTemplate", func(t *testing.T) {
var buf2 bytes.Buffer

if changesSeen := Manifests(specRelease, specRelease, []string{}, true, 10, "template", &buf2); changesSeen {
t.Error("Unexpected return value from Manifests: Expected the return value to be `false` to indicate that it has NOT seen any change(s), but was `true`")
}

require.Equal(t, "[]", buf2.String())
})

t.Run("OnChangeCustomTemplate", func(t *testing.T) {
var buf1 bytes.Buffer
os.Setenv("HELM_DIFF_TPL", "testdata/customTemplate.tpl")
if changesSeen := Manifests(specBeta, specRelease, []string{}, true, 10, "template", &buf1); !changesSeen {
t.Error("Unexpected return value from Manifests: Expected the return value to be `false` to indicate that it has NOT seen any change(s), but was `true`")
}

require.Equal(t, "Resource name: nginx", buf1.String())
})
}
Loading