-
Notifications
You must be signed in to change notification settings - Fork 292
feature Implementation: Diff between Revisions #6 #22
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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 | ||
} |
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 | ||
} |
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() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Huh, why remove all this? The aliasing is done to keep backward compatibility. I would like to keep that for a while to make that this doesn't break existing CI systems. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oops...!! I didn't remove it. just rearranged the code syntatically. chartCommand := newChartCommand()
cmd := &cobra.Command{
Use: "diff",
Short: "Show manifest differences",
//Alias root command to chart subcommand
Args: chartCommand.Args, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. does this need changes/reverting..?, its exactly the same code..!! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, ok my Mistake, thanks for clearing this up. LGTM There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. removed it |
||
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 | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can move this to a global flag?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my point of view, for executing
suppress-secrets
as a global pre-run , we might need to have a common diff object across all the subcommands and it must be made available in root.goThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
opinions on this..? can this be done in some other way..?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, you are right. Haven't thought of that, maybe leave it as it is for now. I think its more important to have the command cleanly separated. We can deduplicate later.