Skip to content

Commit

Permalink
Merge pull request #22 from aananthraj/feature/revision-diff
Browse files Browse the repository at this point in the history
feature Implementation: Diff between Revisions #6
  • Loading branch information
databus23 authored Apr 26, 2018
2 parents 993b7db + 72467ef commit 9beb907
Show file tree
Hide file tree
Showing 4 changed files with 231 additions and 17 deletions.
118 changes: 118 additions & 0 deletions cmd/revision.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package cmd

import (
"errors"
"fmt"
"os"
"strconv"

"github.com/databus23/helm-diff/diff"
"github.com/databus23/helm-diff/manifest"
"github.com/spf13/cobra"
"k8s.io/helm/pkg/helm"
)

type revision struct {
release string
client helm.Interface
suppressedKinds []string
revisions []string
}

const revisionCmdLongUsage = `
This command compares the manifests details of a named release.
It can be used to compare the manifests of
- lastest REVISION with specified REVISION
$ helm diff revision [flags] RELEASE REVISION1
Example:
$ helm diff revision my-release 2
- REVISION1 with REVISION2
$ helm diff revision [flags] RELEASE REVISION1 REVISION2
Example:
$ helm diff revision my-release 2 3
`

func revisionCmd() *cobra.Command {
diff := revision{}
revisionCmd := &cobra.Command{
Use: "revision [flags] RELEASE REVISION1 [REVISION2]",
Short: "Shows diff between revision's manifests",
Long: revisionCmdLongUsage,
RunE: func(cmd *cobra.Command, args []string) error {
if v, _ := cmd.Flags().GetBool("version"); v {
fmt.Println(Version)
return nil
}

switch {
case len(args) < 2:
return errors.New("Too few arguments to Command \"revision\".\nMinimum 2 arguments required: release name, revision")
case len(args) > 3:
return errors.New("Too many arguments to Command \"revision\".\nMaximum 3 arguments allowed: release name, revision1, revision2")
}

if q, _ := cmd.Flags().GetBool("suppress-secrets"); q {
diff.suppressedKinds = append(diff.suppressedKinds, "Secret")
}

diff.release = args[0]
diff.revisions = args[1:]
if diff.client == nil {
diff.client = helm.NewClient(helm.Host(os.Getenv("TILLER_HOST")), helm.ConnectTimeout(int64(30)))
}
return diff.differentiate()
},
}

revisionCmd.Flags().BoolP("suppress-secrets", "q", false, "suppress secrets in the output")
revisionCmd.Flags().StringArrayVar(&diff.suppressedKinds, "suppress", []string{}, "allows suppression of the values listed in the diff output")
revisionCmd.SuggestionsMinimumDistance = 1
return revisionCmd
}

func (d *revision) differentiate() error {

switch len(d.revisions) {
case 1:
releaseResponse, err := d.client.ReleaseContent(d.release)

if err != nil {
return prettyError(err)
}

revision, _ := strconv.Atoi(d.revisions[0])
revisionResponse, err := d.client.ReleaseContent(d.release, helm.ContentReleaseVersion(int32(revision)))
if err != nil {
return prettyError(err)
}

diff.DiffManifests(manifest.Parse(revisionResponse.Release.Manifest), manifest.Parse(releaseResponse.Release.Manifest), d.suppressedKinds, os.Stdout)

case 2:
revision1, _ := strconv.Atoi(d.revisions[0])
revision2, _ := strconv.Atoi(d.revisions[1])
if revision1 > revision2 {
revision1, revision2 = revision2, revision1
}

revisionResponse1, err := d.client.ReleaseContent(d.release, helm.ContentReleaseVersion(int32(revision1)))
if err != nil {
return prettyError(err)
}

revisionResponse2, err := d.client.ReleaseContent(d.release, helm.ContentReleaseVersion(int32(revision2)))
if err != nil {
return prettyError(err)
}

diff.DiffManifests(manifest.Parse(revisionResponse1.Release.Manifest), manifest.Parse(revisionResponse2.Release.Manifest), d.suppressedKinds, os.Stdout)

default:
return errors.New("Invalid Arguments")
}

return nil
}
86 changes: 86 additions & 0 deletions cmd/rollback.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package cmd

import (
"fmt"
"os"
"strconv"

"github.com/databus23/helm-diff/diff"
"github.com/databus23/helm-diff/manifest"
"github.com/spf13/cobra"
"k8s.io/helm/pkg/helm"
)

type rollback struct {
release string
client helm.Interface
suppressedKinds []string
revisions []string
}

const rollbackCmdLongUsage = `
This command compares the laset manifests details of a named release
with specific revision values to rollback.
It forecasts/visualizes changes, that a helm rollback could perform.
`

func rollbackCmd() *cobra.Command {
diff := rollback{}
rollbackCmd := &cobra.Command{
Use: "rollback [flags] [RELEASE] [REVISION]",
Short: "Show a diff explaining what a helm rollback could perform",
Long: rollbackCmdLongUsage,
Example: " helm diff rollback my-release 2",
RunE: func(cmd *cobra.Command, args []string) error {
if v, _ := cmd.Flags().GetBool("version"); v {
fmt.Println(Version)
return nil
}

if err := checkArgsLength(len(args), "release name", "revision number"); err != nil {
return err
}

if q, _ := cmd.Flags().GetBool("suppress-secrets"); q {
diff.suppressedKinds = append(diff.suppressedKinds, "Secret")
}

diff.release = args[0]
diff.revisions = args[1:]

if diff.client == nil {
diff.client = helm.NewClient(helm.Host(os.Getenv("TILLER_HOST")), helm.ConnectTimeout(int64(30)))
}

return diff.backcast()
},
}

rollbackCmd.Flags().BoolP("suppress-secrets", "q", false, "suppress secrets in the output")
rollbackCmd.Flags().StringArrayVar(&diff.suppressedKinds, "suppress", []string{}, "allows suppression of the values listed in the diff output")
rollbackCmd.SuggestionsMinimumDistance = 1
return rollbackCmd
}

func (d *rollback) backcast() error {

// get manifest of the latest release
releaseResponse, err := d.client.ReleaseContent(d.release)

if err != nil {
return prettyError(err)
}

// get manifest of the release to rollback
revision, _ := strconv.Atoi(d.revisions[0])
revisionResponse, err := d.client.ReleaseContent(d.release, helm.ContentReleaseVersion(int32(revision)))
if err != nil {
return prettyError(err)
}

// create a diff between the current manifest and the version of the manifest that a user is intended to rollback
diff.DiffManifests(manifest.Parse(releaseResponse.Release.Manifest), manifest.Parse(revisionResponse.Release.Manifest), d.suppressedKinds, os.Stdout)

return nil
}
38 changes: 27 additions & 11 deletions cmd/root.go
Original file line number Diff line number Diff line change
@@ -1,25 +1,41 @@
package cmd

import "github.com/spf13/cobra"
import (
"github.com/mgutz/ansi"
"github.com/spf13/cobra"
)

func New() *cobra.Command {

chartCommand := newChartCommand()

cmd := &cobra.Command{
Use: "diff",
Short: "Show manifest differences",
//Alias root command to chart subcommand
Args: chartCommand.Args,
// parse the flags and check for actions like suppress-secrets, no-colors
PersistentPreRun: func(cmd *cobra.Command, args []string) {
if nc, _ := cmd.Flags().GetBool("no-color"); nc {
ansi.DisableColors(true)
}
},
RunE: func(cmd *cobra.Command, args []string) error {
cmd.Println(`Command "helm diff" is deprecated, use "helm diff upgrade" instead`)
return chartCommand.RunE(cmd, args)
},
}

chartCommand := newChartCommand()
cmd.AddCommand(newVersionCmd(), chartCommand)
//Alias root command to chart subcommand
cmd.Args = chartCommand.Args
// add no-color as global flag
cmd.PersistentFlags().Bool("no-color", false, "remove colors from the output")
// add flagset from chartCommand
cmd.Flags().AddFlagSet(chartCommand.Flags())
cmd.RunE = func(cmd *cobra.Command, args []string) error {
cmd.Println(`Command "helm diff" is deprecated, use "helm diff upgrade" instead`)
return chartCommand.RunE(cmd, args)
}
cmd.AddCommand(newVersionCmd(), chartCommand)
// add subcommands
cmd.AddCommand(
revisionCmd(),
rollbackCmd(),
)
cmd.SetHelpCommand(&cobra.Command{}) // Disable the help command

return cmd

}
6 changes: 0 additions & 6 deletions cmd/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (

"github.com/databus23/helm-diff/diff"
"github.com/databus23/helm-diff/manifest"
"github.com/mgutz/ansi"
"github.com/spf13/cobra"
"k8s.io/helm/pkg/helm"
)
Expand Down Expand Up @@ -47,10 +46,6 @@ func newChartCommand() *cobra.Command {
diff.suppressedKinds = append(diff.suppressedKinds, "Secret")
}

if nc, _ := cmd.Flags().GetBool("no-color"); nc {
ansi.DisableColors(true)
}

diff.release = args[0]
diff.chart = args[1]
if diff.client == nil {
Expand All @@ -63,7 +58,6 @@ func newChartCommand() *cobra.Command {
f := cmd.Flags()
f.StringVar(&diff.chartVersion, "version", "", "specify the exact chart version to use. If this is not specified, the latest version is used")
f.BoolP("suppress-secrets", "q", false, "suppress secrets in the output")
f.Bool("no-color", false, "remove colors from the output")
f.VarP(&diff.valueFiles, "values", "f", "specify values in a YAML file (can specify multiple)")
f.StringArrayVar(&diff.values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
f.BoolVar(&diff.reuseValues, "reuse-values", false, "reuse the last release's values and merge in any new values")
Expand Down

0 comments on commit 9beb907

Please sign in to comment.