Skip to content

Commit

Permalink
Display values diff on upgrade
Browse files Browse the repository at this point in the history
Only show diff if non-empty string

 - Disabled by default to prevent sensitive values from being leaked.
 - Also changed website in Chart.yaml
 - Added to readme
  • Loading branch information
David Tuite committed Apr 19, 2020
1 parent 40ae5db commit e0c7ec8
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 220 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ This will produce the following effect:
| `googlechat.webhookUrl` | `KW_GOOGLECHAT_WEBHOOK_URL` | | The Google Hangouts Chat URL to use. Must be provided by user. |
| `namespaceToWatch` | `KW_NAMESPACE` | `""` | The cluster namespace to watch for Helm operations in. Leave blank to watch all namespaces. |
| `messagePrefix` | `KW_MESSAGE_PREFIX` | | A prefix for every notification sent. Often used to identify the cluster (production, staging etc). |
| `chartValuesDiff.enabled` | `KW_CHART_VALUES_DIFF_ENABLED` | `false` | When `true`, KubeWise will log a diff of the chart values when a package is upgraded or rolled back. This is useful for visualizing changes between package versions. Be extremely careful with this feature as it can leak sensitive chart values. |
| `image.repository` | | `us.gcr.io/larder-prod/kubewise` | Image repository |
| `image.tag` | | `<VERSION>` | Image tag |
| `replicaCount` | | `1` | Number of KubeWise pods to deploy. More than 1 is not desirable |
Expand Down
12 changes: 7 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,19 @@ module github.com/larderdev/kubewise
go 1.14

require (
github.com/Azure/go-autorest v14.0.0+incompatible
github.com/jmoiron/sqlx v1.2.0 // indirect
github.com/lib/pq v1.3.0 // indirect
github.com/Azure/go-autorest v14.0.0+incompatible
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 // indirect
github.com/olekukonko/tablewriter v0.0.2
github.com/rubenv/sql-migrate v0.0.0-20200402132117-435005d389bc // indirect
github.com/pmezard/go-difflib v1.0.0
github.com/slack-go/slack v0.6.3
golang.org/x/lint v0.0.0-20200302205851-738671d3881b // indirect
golang.org/x/tools v0.0.0-20200410194907-79a7a3126eef // indirect
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b // indirect
golang.org/x/sys v0.0.0-20191220142924-d4481acd189f // indirect
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
google.golang.org/appengine v1.6.5 // indirect
helm.sh/helm/v3 v3.1.1
k8s.io/api v0.17.3
k8s.io/apimachinery v0.17.3
k8s.io/client-go v0.17.2
k8s.io/helm v2.16.5+incompatible
)
220 changes: 12 additions & 208 deletions go.sum

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion helm_chart/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@ sources:
maintainers:
- name: davidtuite
email: [email protected]
url: https://www.davidtuite.com
url: https://www.larder.dev/kubewise

icon: https://github.com/larderdev/kubewise/blob/master/assets/kubewise-mark-blue-512x512.png
2 changes: 2 additions & 0 deletions helm_chart/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,5 @@ spec:
value: "{{ .Values.webhook.method }}"
- name: KW_WEBHOOK_URL
value: "{{ .Values.webhook.url }}"
- name: KW_CHART_VALUES_DIFF_ENABLED
value: "{{ .Values.chartValuesDiff.enabled }}"
3 changes: 3 additions & 0 deletions helm_chart/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ webhook:
namespaceToWatch: ""
messagePrefix:

chartValuesDiff:
enabled: false

serviceAccount:
# Specifies whether a service account should be created
create: true
Expand Down
47 changes: 47 additions & 0 deletions kwrelease/event.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package kwrelease

import (
"fmt"
"log"
"strconv"
"strings"

"github.com/pmezard/go-difflib/difflib"
"helm.sh/helm/v3/pkg/chartutil"
rspb "helm.sh/helm/v3/pkg/release"
api_v1 "k8s.io/api/core/v1"
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -38,6 +41,8 @@ func (e *Event) Init() error {
e.currentRelease = e.GetRelease(e.CurrentReleaseSecret.Name)
e.previousRelease = e.getPreviousRelease()

e.GetConfigDiffYAML()

return nil
}

Expand Down Expand Up @@ -137,6 +142,48 @@ func (e *Event) IsAppVersionChanged() bool {
return e.GetAppVersion() != e.GetPreviousAppVersion()
}

// GetConfigDiffYAML is useful to show what has changed during a chart upgrade or rollback. It
// will show a diff of the values file in the Slack message or other notification. Be careful
// with secrets.
func (e *Event) GetConfigDiffYAML() string {
currentReleaseConfigYAML, err := chartutil.Values(e.currentRelease.Config).YAML()

if err != nil {
// Do NOT log the values. Could leak sensitive data.
log.Println("Error rendering current release config to YAML for application:", e.GetAppName())
return ""
}

if e.previousRelease == nil {
return fmt.Sprintf("%s\n", currentReleaseConfigYAML)
}

previousReleaseConfigYAML, err := chartutil.Values(e.previousRelease.Config).YAML()

if err != nil {
// Do NOT log the values. Could leak sensitive data.
log.Println("Error rendering previous release config to YAML for application:", e.GetAppName())
return ""
}

diff := difflib.UnifiedDiff{
A: difflib.SplitLines(previousReleaseConfigYAML),
B: difflib.SplitLines(currentReleaseConfigYAML),
FromFile: "Old Values",
ToFile: "New Values",
Context: 3,
}

diffText, err := difflib.GetUnifiedDiffString(diff)

if err != nil {
log.Println("Error diffing chart for application:", e.GetAppName())
return ""
}

return diffText
}

// GetAction returns the action which is being performed in this Event. It may be an install,
// upgrade or other Event.
func (e *Event) GetAction() Action {
Expand Down
33 changes: 27 additions & 6 deletions presenters/text.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package presenters

import (
"fmt"
"log"
"os"
"strconv"
"strings"
Expand All @@ -26,6 +27,21 @@ func getChangeInAppVersion(releaseEvent *kwrelease.Event) string {
return appVersion
}

func getConfigDiff(releaseEvent *kwrelease.Event) string {
showDiff, err := strconv.ParseBool(os.Getenv("KW_CHART_VALUES_DIFF_ENABLED"))

if err != nil {
log.Println("Invalid value passed for environment variable KW_CHART_VALUES_DIFF_ENABLED. Boolean required.")
}

configDiffYAML := releaseEvent.GetConfigDiffYAML()
if showDiff && configDiffYAML != "" {
return fmt.Sprintf("\n```%s```", configDiffYAML)
}

return ""
}

// PrepareMsg prepares a short, markdown-like message which is suitable for sending to chat
// applications like Slack. Formatting like *text* us used to add emphasis. This is supported by
// both Slack and Google Chat. Emoji are also used liberally.
Expand All @@ -51,6 +67,10 @@ func PrepareMsg(releaseEvent *kwrelease.Event) string {
getChangeInAppVersion(releaseEvent),
)

if configDiff := getConfigDiff(releaseEvent); configDiff != "" {
msg += configDiff
}

case kwrelease.ActionPreRollback:
msg += fmt.Sprintf("⏬ Rolling back *%s* from version %s to version *%s* in namespace *%s* via Helm. ⏳\n%s",
releaseEvent.GetAppName(),
Expand All @@ -60,6 +80,10 @@ func PrepareMsg(releaseEvent *kwrelease.Event) string {
getChangeInAppVersion(releaseEvent),
)

if configDiff := getConfigDiff(releaseEvent); configDiff != "" {
msg += configDiff
}

case kwrelease.ActionPreUninstall:
msg += fmt.Sprintf("🧼 Uninstalling *%s* from namespace *%s* via Helm. ⏳",
releaseEvent.GetAppName(),
Expand All @@ -75,30 +99,27 @@ func PrepareMsg(releaseEvent *kwrelease.Event) string {
)

case kwrelease.ActionPostUpgrade:
msg += fmt.Sprintf("⏫ Upgraded *%s* from version %s to version *%s* in namespace *%s* via Helm. ✅\n\n```%s```",
msg += fmt.Sprintf("⏫ Upgraded *%s* from version %s to version *%s* in namespace *%s* via Helm. ✅",
releaseEvent.GetAppName(),
releaseEvent.GetPreviousChartVersion(),
releaseEvent.GetChartVersion(),
releaseEvent.GetNamespace(),
releaseEvent.GetNotes(),
)

case kwrelease.ActionPostRollback:
msg += fmt.Sprintf("⏬ Rolled back *%s* from version %s to version *%s* in namespace *%s* via Helm. ✅\n\n```%s```",
msg += fmt.Sprintf("⏬ Rolled back *%s* from version %s to version *%s* in namespace *%s* via Helm. ✅",
releaseEvent.GetAppName(),
releaseEvent.GetPreviousChartVersion(),
releaseEvent.GetChartVersion(),
releaseEvent.GetNamespace(),
releaseEvent.GetNotes(),
)

case kwrelease.ActionPostReplace:
msg += fmt.Sprintf("Replaced *%s* version %s with version *%s* in namespace *%s* via Helm. ✅\n\n```%s```",
msg += fmt.Sprintf("Replaced *%s* version %s with version *%s* in namespace *%s* via Helm. ✅",
releaseEvent.GetAppName(),
releaseEvent.GetPreviousChartVersion(),
releaseEvent.GetChartVersion(),
releaseEvent.GetNamespace(),
releaseEvent.GetNotes(),
)

case kwrelease.ActionFailedInstall:
Expand Down

0 comments on commit e0c7ec8

Please sign in to comment.