Skip to content

Support of helm 3 #150

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

Closed
wants to merge 1 commit into from
Closed
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
141 changes: 138 additions & 3 deletions cmd/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,27 @@ package cmd

import (
"fmt"
"log"
"os"
"path/filepath"
"sync"

flag "github.com/spf13/pflag"
"helm.sh/helm/pkg/action"
"helm.sh/helm/pkg/cli"
"helm.sh/helm/pkg/cli/values"
"helm.sh/helm/pkg/kube"
rspb "helm.sh/helm/pkg/release"
"helm.sh/helm/pkg/storage"
"helm.sh/helm/pkg/storage/driver"
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/client-go/util/homedir"
"k8s.io/helm/pkg/helm"
helm_env "k8s.io/helm/pkg/helm/environment"
rls "k8s.io/helm/pkg/proto/hapi/services"
"k8s.io/helm/pkg/tlsutil"

"github.com/databus23/helm-diff/manifest"
)

const (
Expand All @@ -22,13 +35,135 @@ var (
settings helm_env.EnvSettings
// DefaultHelmHome to hold default home path of .helm dir
DefaultHelmHome = filepath.Join(homedir.HomeDir(), ".helm")
settingsV3 *cli.EnvSettings
config genericclioptions.RESTClientGetter
configOnce sync.Once
)

type clientHolder struct {
client helm.Interface
actionConfig action.Configuration
}

func addCommonCmdOptions(f *flag.FlagSet) {
settings.AddFlagsTLS(f)
settings.InitTLS(f)
if isHelm3() {
settingsV3 = cli.New()
settingsV3.AddFlags(f)
settingsV3.Init(f)
} else {
settings.AddFlagsTLS(f)
settings.InitTLS(f)

f.StringVar((*string)(&settings.Home), "home", DefaultHelmHome, "location of your Helm config. Overrides $HELM_HOME")
}
}

func (cmd *clientHolder) deployedRelease(release string) (releaseResponse manifest.ReleaseResponse, err error) {
if isHelm3() {
var response *rspb.Release
response, err = cmd.actionConfig.Releases.Deployed(release)
releaseResponse.ReleaseV3 = response
} else {
var response *rls.GetReleaseContentResponse
response, err = cmd.client.ReleaseContent(release)
releaseResponse.Release = response.Release
}
return
}

func (cmd *clientHolder) deployedReleaseRevision(release string, version int) (releaseResponse manifest.ReleaseResponse, err error) {
if isHelm3() {
var response *rspb.Release
response, err = cmd.actionConfig.Releases.Get(release, version)
releaseResponse.ReleaseV3 = response
} else {
var response *rls.GetReleaseContentResponse
response, err = cmd.client.ReleaseContent(release, helm.ContentReleaseVersion(int32(version)))
releaseResponse.Release = response.Release
}
return
}

func (cmd *clientHolder) init() {
if isHelm3() {
if cmd.actionConfig.Releases == nil {
initActionConfig(&cmd.actionConfig)
}
} else {
if cmd.client == nil {
cmd.client = createHelmClient()
}
}
}

func isHelm3() bool {
return os.Getenv("TILLER_HOST") == ""
}

func addValueOptionsFlags(f *flag.FlagSet, v *values.Options) {
f.StringSliceVarP(&v.ValueFiles, "values", "f", []string{}, "specify values in a YAML file or a URL(can specify multiple)")
f.StringArrayVar(&v.Values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
f.StringArrayVar(&v.StringValues, "set-string", []string{}, "set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)")
}

func initActionConfig(actionConfig *action.Configuration) {
kc := kube.New(kubeConfig())
kc.Log = debugV3

clientset, err := kc.Factory.KubernetesClientSet()
if err != nil {
// TODO return error
log.Fatal(err)
}
namespace := getNamespace()

var store *storage.Storage
switch os.Getenv("HELM_DRIVER") {
case "secret", "secrets", "":
d := driver.NewSecrets(clientset.CoreV1().Secrets(namespace))
d.Log = debugV3
store = storage.Init(d)
case "configmap", "configmaps":
d := driver.NewConfigMaps(clientset.CoreV1().ConfigMaps(namespace))
d.Log = debugV3
store = storage.Init(d)
case "memory":
d := driver.NewMemory()
store = storage.Init(d)
default:
// Not sure what to do here.
panic("Unknown driver in HELM_DRIVER: " + os.Getenv("HELM_DRIVER"))
}

actionConfig.RESTClientGetter = kubeConfig()
actionConfig.KubeClient = kc
actionConfig.Releases = store
actionConfig.Log = debugV3
}

func getNamespace() string {
if settingsV3.Namespace != "" {
return settingsV3.Namespace
}

f.StringVar((*string)(&settings.Home), "home", DefaultHelmHome, "location of your Helm config. Overrides $HELM_HOME")
if ns, _, err := kubeConfig().ToRawKubeConfigLoader().Namespace(); err == nil {
return ns
}
return "default"
}

func kubeConfig() genericclioptions.RESTClientGetter {
configOnce.Do(func() {
config = kube.GetConfig(settingsV3.KubeConfig, settingsV3.KubeContext, settingsV3.Namespace)
})
return config
}

func debugV3(format string, v ...interface{}) {
if settingsV3.Debug {
format = fmt.Sprintf("[debug] %s\n", format)
log.Output(2, fmt.Sprintf(format, v...))
}
}

func createHelmClient() helm.Interface {
Expand Down
17 changes: 7 additions & 10 deletions cmd/release.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@ import (
"os"

"github.com/spf13/cobra"
"k8s.io/helm/pkg/helm"

"github.com/databus23/helm-diff/diff"
"github.com/databus23/helm-diff/manifest"
)

type release struct {
client helm.Interface
clientHolder
detailedExitCode bool
suppressedKinds []string
releases []string
Expand Down Expand Up @@ -60,9 +59,7 @@ func releaseCmd() *cobra.Command {
}

diff.releases = args[0:]
if diff.client == nil {
diff.client = createHelmClient()
}
diff.init()
return diff.differentiate()
},
}
Expand All @@ -80,20 +77,20 @@ func releaseCmd() *cobra.Command {

func (d *release) differentiate() error {

releaseResponse1, err := d.client.ReleaseContent(d.releases[0])
releaseResponse1, err := d.deployedRelease(d.releases[0])
if err != nil {
return prettyError(err)
}

releaseResponse2, err := d.client.ReleaseContent(d.releases[1])
releaseResponse2, err := d.deployedRelease(d.releases[1])
if err != nil {
return prettyError(err)
}

if releaseResponse1.Release.Chart.Metadata.Name == releaseResponse2.Release.Chart.Metadata.Name {
if releaseResponse1.ChartName() == releaseResponse2.ChartName() {
seenAnyChanges := diff.Releases(
manifest.ParseRelease(releaseResponse1.Release, d.includeTests),
manifest.ParseRelease(releaseResponse2.Release, d.includeTests),
manifest.ParseRelease(releaseResponse1, d.includeTests),
manifest.ParseRelease(releaseResponse2, d.includeTests),
d.suppressedKinds,
d.outputContext,
os.Stdout)
Expand Down
25 changes: 11 additions & 14 deletions cmd/revision.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,14 @@ import (
"strconv"

"github.com/spf13/cobra"
"k8s.io/helm/pkg/helm"

"github.com/databus23/helm-diff/diff"
"github.com/databus23/helm-diff/manifest"
)

type revision struct {
release string
client helm.Interface
release string
clientHolder
detailedExitCode bool
suppressedKinds []string
revisions []string
Expand Down Expand Up @@ -70,9 +69,7 @@ func revisionCmd() *cobra.Command {

diff.release = args[0]
diff.revisions = args[1:]
if diff.client == nil {
diff.client = createHelmClient()
}
diff.init()
return diff.differentiate()
},
}
Expand All @@ -92,21 +89,21 @@ func (d *revision) differentiate() error {

switch len(d.revisions) {
case 1:
releaseResponse, err := d.client.ReleaseContent(d.release)
releaseResponse, err := d.deployedRelease(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)))
revisionResponse, err := d.deployedReleaseRevision(d.release, revision)
if err != nil {
return prettyError(err)
}

diff.Manifests(
manifest.ParseRelease(revisionResponse.Release, d.includeTests),
manifest.ParseRelease(releaseResponse.Release, d.includeTests),
manifest.ParseRelease(revisionResponse, d.includeTests),
manifest.ParseRelease(releaseResponse, d.includeTests),
d.suppressedKinds,
d.outputContext,
os.Stdout)
Expand All @@ -118,19 +115,19 @@ func (d *revision) differentiate() error {
revision1, revision2 = revision2, revision1
}

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

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

seenAnyChanges := diff.Manifests(
manifest.ParseRelease(revisionResponse1.Release, d.includeTests),
manifest.ParseRelease(revisionResponse2.Release, d.includeTests),
manifest.ParseRelease(revisionResponse1, d.includeTests),
manifest.ParseRelease(revisionResponse2, d.includeTests),
d.suppressedKinds,
d.outputContext,
os.Stdout)
Expand Down
17 changes: 7 additions & 10 deletions cmd/rollback.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,14 @@ import (
"strconv"

"github.com/spf13/cobra"
"k8s.io/helm/pkg/helm"

"github.com/databus23/helm-diff/diff"
"github.com/databus23/helm-diff/manifest"
)

type rollback struct {
release string
client helm.Interface
release string
clientHolder
detailedExitCode bool
suppressedKinds []string
revisions []string
Expand Down Expand Up @@ -60,9 +59,7 @@ func rollbackCmd() *cobra.Command {
diff.release = args[0]
diff.revisions = args[1:]

if diff.client == nil {
diff.client = createHelmClient()
}
diff.init()

return diff.backcast()
},
Expand All @@ -82,23 +79,23 @@ func rollbackCmd() *cobra.Command {
func (d *rollback) backcast() error {

// get manifest of the latest release
releaseResponse, err := d.client.ReleaseContent(d.release)
releaseResponse, err := d.deployedRelease(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)))
revisionResponse, err := d.deployedReleaseRevision(d.release, 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
seenAnyChanges := diff.Manifests(
manifest.ParseRelease(releaseResponse.Release, d.includeTests),
manifest.ParseRelease(revisionResponse.Release, d.includeTests),
manifest.ParseRelease(releaseResponse, d.includeTests),
manifest.ParseRelease(revisionResponse, d.includeTests),
d.suppressedKinds,
d.outputContext,
os.Stdout)
Expand Down
Loading