Skip to content
Draft
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
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,9 @@ Usage:
Examples:
helm diff upgrade my-release stable/postgresql --values values.yaml

# Use a specific kubeconfig context
helm diff upgrade my-release stable/postgresql --kube-context production

# Set HELM_DIFF_IGNORE_UNKNOWN_FLAGS=true to ignore unknown flags
# It's useful when you're using `helm-diff` in a `helm upgrade` wrapper.
# See https://github.com/databus23/helm-diff/issues/278 for more information.
Expand Down Expand Up @@ -191,6 +194,7 @@ Flags:
--include-tests enable the diffing of the helm test hooks
--insecure-skip-tls-verify skip tls certificate checks for the chart download
--install enables diffing of releases that are not yet deployed via Helm (equivalent to --allow-unreleased, added to match "helm upgrade --install" command
--kube-context string name of the kubeconfig context to use
--kube-version string Kubernetes version used for Capabilities.KubeVersion
--kubeconfig string This flag is ignored, to allow passing of this top level flag to helm
--no-hooks disable diffing of hooks
Expand Down
29 changes: 25 additions & 4 deletions cmd/helm3.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,38 +65,50 @@ func compatibleHelm3Version() error {
return nil
}

func getRelease(release, namespace string) ([]byte, error) {
func getRelease(release, namespace, kubeContext string) ([]byte, error) {
args := []string{"get", "manifest", release}
if namespace != "" {
args = append(args, "--namespace", namespace)
}
if kubeContext != "" {
args = append(args, "--kube-context", kubeContext)
}
cmd := exec.Command(os.Getenv("HELM_BIN"), args...)
return outputWithRichError(cmd)
}

func getHooks(release, namespace string) ([]byte, error) {
func getHooks(release, namespace, kubeContext string) ([]byte, error) {
args := []string{"get", "hooks", release}
if namespace != "" {
args = append(args, "--namespace", namespace)
}
if kubeContext != "" {
args = append(args, "--kube-context", kubeContext)
}
cmd := exec.Command(os.Getenv("HELM_BIN"), args...)
return outputWithRichError(cmd)
}

func getRevision(release string, revision int, namespace string) ([]byte, error) {
func getRevision(release string, revision int, namespace, kubeContext string) ([]byte, error) {
args := []string{"get", "manifest", release, "--revision", strconv.Itoa(revision)}
if namespace != "" {
args = append(args, "--namespace", namespace)
}
if kubeContext != "" {
args = append(args, "--kube-context", kubeContext)
}
cmd := exec.Command(os.Getenv("HELM_BIN"), args...)
return outputWithRichError(cmd)
}

func getChart(release, namespace string) (string, error) {
func getChart(release, namespace, kubeContext string) (string, error) {
args := []string{"get", "all", release, "--template", "{{.Release.Chart.Name}}"}
if namespace != "" {
args = append(args, "--namespace", namespace)
}
if kubeContext != "" {
args = append(args, "--kube-context", kubeContext)
}
cmd := exec.Command(os.Getenv("HELM_BIN"), args...)
out, err := outputWithRichError(cmd)
if err != nil {
Expand Down Expand Up @@ -125,6 +137,9 @@ func (d *diffCmd) template(isUpgrade bool) ([]byte, error) {
if d.namespace != "" {
flags = append(flags, "--namespace", d.namespace)
}
if d.kubeContext != "" {
flags = append(flags, "--kube-context", d.kubeContext)
}
if d.postRenderer != "" {
flags = append(flags, "--post-renderer", d.postRenderer)
}
Expand Down Expand Up @@ -341,6 +356,12 @@ func (d *diffCmd) writeExistingValues(f *os.File, all bool) error {
if all {
args = append(args, "--all")
}
if d.namespace != "" {
args = append(args, "--namespace", d.namespace)
}
if d.kubeContext != "" {
args = append(args, "--kube-context", d.kubeContext)
}
cmd := exec.Command(os.Getenv("HELM_BIN"), args...)
debugPrint("Executing %s", strings.Join(cmd.Args, " "))
defer func() {
Expand Down
86 changes: 86 additions & 0 deletions cmd/kube_context_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package cmd

import (
"testing"
)

func TestKubeContextFlag(t *testing.T) {
tests := []struct {
name string
kubeContext string
expected bool
}{
{
name: "with kube-context",
kubeContext: "test-context",
expected: true,
},
{
name: "without kube-context",
kubeContext: "",
expected: false,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Test diffCmd struct
d := &diffCmd{
kubeContext: tt.kubeContext,
namespace: "test-namespace",
}

// Verify the field is set correctly
if (d.kubeContext != "") != tt.expected {
t.Errorf("kubeContext field: expected %v, got %v", tt.expected, d.kubeContext != "")
}

// Test release struct
r := &release{
kubeContext: tt.kubeContext,
}

if (r.kubeContext != "") != tt.expected {
t.Errorf("release kubeContext field: expected %v, got %v", tt.expected, r.kubeContext != "")
}

// Test revision struct
rev := &revision{
kubeContext: tt.kubeContext,
}

if (rev.kubeContext != "") != tt.expected {
t.Errorf("revision kubeContext field: expected %v, got %v", tt.expected, rev.kubeContext != "")
}

// Test rollback struct
rb := &rollback{
kubeContext: tt.kubeContext,
}

if (rb.kubeContext != "") != tt.expected {
t.Errorf("rollback kubeContext field: expected %v, got %v", tt.expected, rb.kubeContext != "")
}
})
}
}

func TestKubeContextInDiffCmd(t *testing.T) {
// Test that the diffCmd has the kubeContext field in the struct
d := diffCmd{
kubeContext: "test-context",
namespace: "test-namespace",
release: "test-release",
chart: "test-chart",
}

if d.kubeContext != "test-context" {
t.Errorf("Expected kubeContext to be 'test-context', got '%s'", d.kubeContext)
}

// Test that the field can be set to empty
d.kubeContext = ""
if d.kubeContext != "" {
t.Errorf("Expected kubeContext to be empty, got '%s'", d.kubeContext)
}
}
10 changes: 6 additions & 4 deletions cmd/release.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type release struct {
releases []string
includeTests bool
normalizeManifests bool
kubeContext string
diff.Options
}

Expand Down Expand Up @@ -63,6 +64,7 @@ func releaseCmd() *cobra.Command {
releaseCmd.Flags().BoolVar(&diff.detailedExitCode, "detailed-exitcode", false, "return a non-zero exit code when there are changes")
releaseCmd.Flags().BoolVar(&diff.includeTests, "include-tests", false, "enable the diffing of the helm test hooks")
releaseCmd.Flags().BoolVar(&diff.normalizeManifests, "normalize-manifests", false, "normalize manifests before running diff to exclude style differences from the output")
releaseCmd.Flags().StringVar(&diff.kubeContext, "kube-context", "", "name of the kubeconfig context to use")
AddDiffOptions(releaseCmd.Flags(), &diff.Options)

releaseCmd.SuggestionsMinimumDistance = 1
Expand All @@ -82,11 +84,11 @@ func (d *release) differentiateHelm3() error {
namespace1 = strings.Split(release1, "/")[0]
release1 = strings.Split(release1, "/")[1]
}
releaseResponse1, err := getRelease(release1, namespace1)
releaseResponse1, err := getRelease(release1, namespace1, d.kubeContext)
if err != nil {
return err
}
releaseChart1, err := getChart(release1, namespace1)
releaseChart1, err := getChart(release1, namespace1, d.kubeContext)
if err != nil {
return err
}
Expand All @@ -97,11 +99,11 @@ func (d *release) differentiateHelm3() error {
namespace2 = strings.Split(release2, "/")[0]
release2 = strings.Split(release2, "/")[1]
}
releaseResponse2, err := getRelease(release2, namespace2)
releaseResponse2, err := getRelease(release2, namespace2, d.kubeContext)
if err != nil {
return err
}
releaseChart2, err := getChart(release2, namespace2)
releaseChart2, err := getChart(release2, namespace2, d.kubeContext)
if err != nil {
return err
}
Expand Down
10 changes: 6 additions & 4 deletions cmd/revision.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type revision struct {
revisions []string
includeTests bool
normalizeManifests bool
kubeContext string
diff.Options
}

Expand Down Expand Up @@ -70,6 +71,7 @@ func revisionCmd() *cobra.Command {
revisionCmd.Flags().BoolVar(&diff.detailedExitCode, "detailed-exitcode", false, "return a non-zero exit code when there are changes")
revisionCmd.Flags().BoolVar(&diff.includeTests, "include-tests", false, "enable the diffing of the helm test hooks")
revisionCmd.Flags().BoolVar(&diff.normalizeManifests, "normalize-manifests", false, "normalize manifests before running diff to exclude style differences from the output")
revisionCmd.Flags().StringVar(&diff.kubeContext, "kube-context", "", "name of the kubeconfig context to use")
AddDiffOptions(revisionCmd.Flags(), &diff.Options)

revisionCmd.SuggestionsMinimumDistance = 1
Expand All @@ -85,14 +87,14 @@ func (d *revision) differentiateHelm3() error {
}
switch len(d.revisions) {
case 1:
releaseResponse, err := getRelease(d.release, namespace)
releaseResponse, err := getRelease(d.release, namespace, d.kubeContext)

if err != nil {
return err
}

revision, _ := strconv.Atoi(d.revisions[0])
revisionResponse, err := getRevision(d.release, revision, namespace)
revisionResponse, err := getRevision(d.release, revision, namespace, d.kubeContext)
if err != nil {
return err
}
Expand All @@ -110,12 +112,12 @@ func (d *revision) differentiateHelm3() error {
revision1, revision2 = revision2, revision1
}

revisionResponse1, err := getRevision(d.release, revision1, namespace)
revisionResponse1, err := getRevision(d.release, revision1, namespace, d.kubeContext)
if err != nil {
return err
}

revisionResponse2, err := getRevision(d.release, revision2, namespace)
revisionResponse2, err := getRevision(d.release, revision2, namespace, d.kubeContext)
if err != nil {
return err
}
Expand Down
6 changes: 4 additions & 2 deletions cmd/rollback.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type rollback struct {
revisions []string
includeTests bool
normalizeManifests bool
kubeContext string
diff.Options
}

Expand Down Expand Up @@ -60,6 +61,7 @@ func rollbackCmd() *cobra.Command {
rollbackCmd.Flags().BoolVar(&diff.detailedExitCode, "detailed-exitcode", false, "return a non-zero exit code when there are changes")
rollbackCmd.Flags().BoolVar(&diff.includeTests, "include-tests", false, "enable the diffing of the helm test hooks")
rollbackCmd.Flags().BoolVar(&diff.normalizeManifests, "normalize-manifests", false, "normalize manifests before running diff to exclude style differences from the output")
rollbackCmd.Flags().StringVar(&diff.kubeContext, "kube-context", "", "name of the kubeconfig context to use")
AddDiffOptions(rollbackCmd.Flags(), &diff.Options)

rollbackCmd.SuggestionsMinimumDistance = 1
Expand All @@ -74,15 +76,15 @@ func (d *rollback) backcastHelm3() error {
excludes = []string{}
}
// get manifest of the latest release
releaseResponse, err := getRelease(d.release, namespace)
releaseResponse, err := getRelease(d.release, namespace, d.kubeContext)

if err != nil {
return err
}

// get manifest of the release to rollback
revision, _ := strconv.Atoi(d.revisions[0])
revisionResponse, err := getRevision(d.release, revision, namespace)
revisionResponse, err := getRevision(d.release, revision, namespace, d.kubeContext)
if err != nil {
return err
}
Expand Down
7 changes: 4 additions & 3 deletions cmd/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ type diffCmd struct {
enableDNS bool
SkipSchemaValidation bool
namespace string // namespace to assume the release to be installed into. Defaults to the current kube config namespace.
kubeContext string // name of the kubeconfig context to use
valueFiles valueFiles
values []string
stringValues []string
Expand Down Expand Up @@ -211,7 +212,7 @@ func newChartCommand() *cobra.Command {
var kubeconfig string
f.StringVar(&kubeconfig, "kubeconfig", "", "This flag is ignored, to allow passing of this top level flag to helm")
f.BoolVar(&diff.threeWayMerge, "three-way-merge", false, "use three-way-merge to compute patch and generate diff output")
// f.StringVar(&diff.kubeContext, "kube-context", "", "name of the kubeconfig context to use")
f.StringVar(&diff.kubeContext, "kube-context", "", "name of the kubeconfig context to use")
f.StringVar(&diff.chartVersion, "version", "", "specify the exact chart version to use. If this is not specified, the latest version is used")
f.StringVar(&diff.chartRepo, "repo", "", "specify the chart repository url to locate the requested chart")
f.BoolVar(&diff.detailedExitCode, "detailed-exitcode", false, "return a non-zero exit code when there are changes")
Expand Down Expand Up @@ -270,7 +271,7 @@ func (d *diffCmd) runHelm3() error {
}

if d.clusterAccessAllowed() {
releaseManifest, err = getRelease(d.release, d.namespace)
releaseManifest, err = getRelease(d.release, d.namespace, d.kubeContext)
}

var newInstall bool
Expand Down Expand Up @@ -313,7 +314,7 @@ func (d *diffCmd) runHelm3() error {
currentSpecs := make(map[string]*manifest.MappingResult)
if !newInstall && d.clusterAccessAllowed() {
if !d.noHooks && !d.threeWayMerge {
hooks, err := getHooks(d.release, d.namespace)
hooks, err := getHooks(d.release, d.namespace, d.kubeContext)
if err != nil {
return err
}
Expand Down
Loading