From 6ebd34f646332138b037db85a19aeaedda31dbc1 Mon Sep 17 00:00:00 2001 From: bbensky Date: Mon, 1 Jul 2024 14:46:01 -0600 Subject: [PATCH 1/5] feat/kubeconfig flag --- cmd/root.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmd/root.go b/cmd/root.go index 6faa65ea..9f1dbd7b 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -67,6 +67,7 @@ var ( noHeaders bool exitCode int noFooter bool + kubeconfig string ) const ( @@ -104,6 +105,7 @@ func init() { detectHelmCmd.PersistentFlags().StringVar(&kubeContext, "kube-context", "", "The kube context to use. If blank, defaults to current context.") rootCmd.AddCommand(detectApiResourceCmd) + detectApiResourceCmd.PersistentFlags().StringVarP(&kubeconfig, "kubeconfig", "", "", "The path to the kubeconfig file to use. If blank, defaults to current kubeconfig.") detectApiResourceCmd.PersistentFlags().StringVarP(&namespace, "namespace", "n", "", "Only detect resources in a specific namespace.") detectApiResourceCmd.PersistentFlags().StringVar(&kubeContext, "kube-context", "", "The kube context to use. If blank, defaults to current context.") From 75c17f82a2ffce7f14dc9339450a7ef84e1849b4 Mon Sep 17 00:00:00 2001 From: bbensky Date: Fri, 19 Jul 2024 13:21:54 -0600 Subject: [PATCH 2/5] kubeconfig clientcmd option --- cmd/root.go | 10 +++++---- pkg/discovery-api/discovery_api.go | 4 ++-- pkg/helm/helm.go | 4 ++-- pkg/kube/kube.go | 34 ++++++++++++++++++++++-------- 4 files changed, 35 insertions(+), 17 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 9f1dbd7b..bc34c99c 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -67,7 +67,7 @@ var ( noHeaders bool exitCode int noFooter bool - kubeconfig string + kubeConfigPath string ) const ( @@ -101,15 +101,17 @@ func init() { detectFilesCmd.PersistentFlags().StringVarP(&directory, "directory", "d", "", "The directory to scan. If blank, defaults to current working dir.") rootCmd.AddCommand(detectHelmCmd) + detectHelmCmd.PersistentFlags().StringVarP(&kubeConfigPath, "kubeconfig", "", "", "The path to the kubeconfig file to use. If blank, defaults to current kubeconfig.") detectHelmCmd.PersistentFlags().StringVarP(&namespace, "namespace", "n", "", "Only detect releases in a specific namespace.") detectHelmCmd.PersistentFlags().StringVar(&kubeContext, "kube-context", "", "The kube context to use. If blank, defaults to current context.") rootCmd.AddCommand(detectApiResourceCmd) - detectApiResourceCmd.PersistentFlags().StringVarP(&kubeconfig, "kubeconfig", "", "", "The path to the kubeconfig file to use. If blank, defaults to current kubeconfig.") + detectApiResourceCmd.PersistentFlags().StringVarP(&kubeConfigPath, "kubeconfig", "", "", "The path to the kubeconfig file to use. If blank, defaults to current kubeconfig.") detectApiResourceCmd.PersistentFlags().StringVarP(&namespace, "namespace", "n", "", "Only detect resources in a specific namespace.") detectApiResourceCmd.PersistentFlags().StringVar(&kubeContext, "kube-context", "", "The kube context to use. If blank, defaults to current context.") rootCmd.AddCommand(detectAllInClusterCmd) + detectAllInClusterCmd.PersistentFlags().StringVarP(&kubeConfigPath, "kubeconfig", "", "", "The path to the kubeconfig file to use. If blank, defaults to current kubeconfig.") detectAllInClusterCmd.PersistentFlags().StringVarP(&namespace, "namespace", "n", "", "Only detect resources in a specific namespace.") detectAllInClusterCmd.PersistentFlags().StringVar(&kubeContext, "kube-context", "", "The kube context to use. If blank, defaults to current context.") @@ -477,7 +479,7 @@ func Execute(VERSION string, COMMIT string, versionsFile []byte) { } func detectHelm() error { - h, err := helm.NewHelm(namespace, kubeContext, apiInstance) + h, err := helm.NewHelm(namespace, kubeContext, apiInstance, kubeConfigPath) if err != nil { return fmt.Errorf("error getting helm configuration: %v", err) } @@ -489,7 +491,7 @@ func detectHelm() error { } func detectAPIResources() error { - disCl, err := discoveryapi.NewDiscoveryClient(namespace, kubeContext, apiInstance) + disCl, err := discoveryapi.NewDiscoveryClient(namespace, kubeContext, apiInstance, kubeConfigPath) if err != nil { return fmt.Errorf("Error creating Discovery REST Client: %v", err) } diff --git a/pkg/discovery-api/discovery_api.go b/pkg/discovery-api/discovery_api.go index d574835a..46b656f6 100644 --- a/pkg/discovery-api/discovery_api.go +++ b/pkg/discovery-api/discovery_api.go @@ -54,13 +54,13 @@ type DiscoveryClient struct { } // NewDiscoveryClient returns a new struct with config portions complete. -func NewDiscoveryClient(namespace string, kubeContext string, instance *api.Instance) (*DiscoveryClient, error) { +func NewDiscoveryClient(namespace string, kubeContext string, instance *api.Instance, kubeConfigPath string) (*DiscoveryClient, error) { cl := &DiscoveryClient{ Instance: instance, } var err error - cl.restConfig, err = kube.GetConfig(kubeContext) + cl.restConfig, err = kube.GetConfig(kubeContext, kubeConfigPath) if err != nil { return nil, err } diff --git a/pkg/helm/helm.go b/pkg/helm/helm.go index c0444178..80f30252 100644 --- a/pkg/helm/helm.go +++ b/pkg/helm/helm.go @@ -74,8 +74,8 @@ type ChartMeta struct { } // NewHelm returns a basic helm struct with the version of helm requested -func NewHelm(namespace string, kubeContext string, instance *api.Instance) (*Helm, error) { - config, err := kube.GetConfigInstance(kubeContext) +func NewHelm(namespace string, kubeContext string, instance *api.Instance, kubeConfigPath string) (*Helm, error) { + config, err := kube.GetConfigInstance(kubeContext, kubeConfigPath) if err != nil { return nil, err } diff --git a/pkg/kube/kube.go b/pkg/kube/kube.go index e184bf87..8cc03c63 100644 --- a/pkg/kube/kube.go +++ b/pkg/kube/kube.go @@ -33,6 +33,7 @@ import ( "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" "k8s.io/klog/v2" // This is required to auth to cloud providers (i.e. GKE) @@ -48,15 +49,15 @@ var kubeClient *Kube var once sync.Once // GetConfigInstance returns a Pluto Kubernetes interface based on the current configuration -func GetConfigInstance(kubeContext string) (*Kube, error) { +func GetConfigInstance(kubeContext string, kubeConfigPath string) (*Kube, error) { var err error var client kubernetes.Interface var kubeConfig *rest.Config - kubeConfig, err = GetConfig(kubeContext) - if err != nil { - return nil, err - } + kubeConfig, err = GetConfig(kubeContext, kubeConfigPath) + if err != nil { + return nil, err + } once.Do(func() { if kubeClient == nil { @@ -74,15 +75,30 @@ func GetConfigInstance(kubeContext string) (*Kube, error) { } // GetConfig returns the current kube config with a specific context -func GetConfig(kubeContext string) (*rest.Config, error) { +func GetConfig(kubeContext string, kubeConfigPath string) (*rest.Config, error) { + var kubeConfig *rest.Config + var err error + if kubeContext != "" { klog.V(3).Infof("using kube context: %s", kubeContext) } - kubeConfig, err := config.GetConfigWithContext(kubeContext) - if err != nil { - return nil, err + if kubeConfigPath != "" { + kubeConfig, err = clientcmd.NewNonInteractiveDeferredLoadingClientConfig( + &clientcmd.ClientConfigLoadingRules{ExplicitPath: kubeConfigPath}, + &clientcmd.ConfigOverrides{ + CurrentContext: kubeContext, + }).ClientConfig() + if err != nil { + return nil, err + } + } else { + kubeConfig, err = config.GetConfigWithContext(kubeContext) + if err != nil { + return nil, err + } } + return kubeConfig, nil } From 2ed3354c6d90452ecdf4840a2621d2d4b46cf231 Mon Sep 17 00:00:00 2001 From: bbensky Date: Fri, 19 Jul 2024 13:55:18 -0600 Subject: [PATCH 3/5] setting kubeconfig env var --- pkg/kube/kube.go | 24 ++++++++--------------- pkg/kube/kube_test.go | 45 +++++++++++++++++++++++++++---------------- 2 files changed, 36 insertions(+), 33 deletions(-) diff --git a/pkg/kube/kube.go b/pkg/kube/kube.go index 8cc03c63..cd9e4ab5 100644 --- a/pkg/kube/kube.go +++ b/pkg/kube/kube.go @@ -29,11 +29,11 @@ package kube import ( + "os" "sync" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" - "k8s.io/client-go/tools/clientcmd" "k8s.io/klog/v2" // This is required to auth to cloud providers (i.e. GKE) @@ -76,27 +76,19 @@ func GetConfigInstance(kubeContext string, kubeConfigPath string) (*Kube, error) // GetConfig returns the current kube config with a specific context func GetConfig(kubeContext string, kubeConfigPath string) (*rest.Config, error) { - var kubeConfig *rest.Config - var err error if kubeContext != "" { klog.V(3).Infof("using kube context: %s", kubeContext) } if kubeConfigPath != "" { - kubeConfig, err = clientcmd.NewNonInteractiveDeferredLoadingClientConfig( - &clientcmd.ClientConfigLoadingRules{ExplicitPath: kubeConfigPath}, - &clientcmd.ConfigOverrides{ - CurrentContext: kubeContext, - }).ClientConfig() - if err != nil { - return nil, err - } - } else { - kubeConfig, err = config.GetConfigWithContext(kubeContext) - if err != nil { - return nil, err - } + klog.V(3).Infof("using kubeconfig at path: %s", kubeConfigPath) + os.Setenv("KUBECONFIG", kubeConfigPath) + } + + kubeConfig, err := config.GetConfigWithContext(kubeContext) + if err != nil { + return nil, err } return kubeConfig, nil diff --git a/pkg/kube/kube_test.go b/pkg/kube/kube_test.go index 7acc514f..401ddf2a 100644 --- a/pkg/kube/kube_test.go +++ b/pkg/kube/kube_test.go @@ -24,34 +24,45 @@ import ( func Test_getKubeClient(t *testing.T) { tests := []struct { - name string - kubeContext string - kubeConfig string - wantErr bool + name string + kubeContext string + kubeConfig string + kubeConfigPath string + wantErr bool }{ { - name: "context does not exist", - kubeContext: "farglebargle", - kubeConfig: "testdata/kubeconfig", - wantErr: true, + name: "context does not exist", + kubeContext: "farglebargle", + kubeConfig: "testdata/kubeconfig", + kubeConfigPath: "", + wantErr: true, }, { - name: "context exists", - kubeContext: "kind-kind", - kubeConfig: "testdata/kubeconfig", - wantErr: false, + name: "context exists", + kubeContext: "kind-kind", + kubeConfig: "testdata/kubeconfig", + kubeConfigPath: "", + wantErr: false, }, { - name: "invalid kubeconfig", - kubeContext: "kind-kind", - kubeConfig: "testdata/kubeconfig_invalid", - wantErr: true, + name: "invalid kubeconfig", + kubeContext: "kind-kind", + kubeConfig: "testdata/kubeconfig_invalid", + kubeConfigPath: "", + wantErr: true, + }, + { + name: "invalid kubeconfig", + kubeContext: "kind-kind", + kubeConfig: "testdata/kubeconfig_invalid", + kubeConfigPath: "", + wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { os.Setenv("KUBECONFIG", tt.kubeConfig) - _, err := GetConfig(tt.kubeContext) + _, err := GetConfig(tt.kubeContext, tt.kubeConfigPath) if tt.wantErr { assert.Error(t, err) } else { From ec80be404c3776176fa260f9e58539828274bbbb Mon Sep 17 00:00:00 2001 From: bbensky Date: Mon, 22 Jul 2024 11:59:21 -0600 Subject: [PATCH 4/5] updating doc and package --- cmd/root.go | 2 +- docs/advanced.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index bc34c99c..52a741c6 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -39,7 +39,7 @@ import ( discoveryapi "github.com/fairwindsops/pluto/v5/pkg/discovery-api" "github.com/fairwindsops/pluto/v5/pkg/finder" "github.com/fairwindsops/pluto/v5/pkg/helm" - "github.com/rogpeppe/go-internal/semver" + "golang.org/x/mod/semver" "github.com/spf13/cobra" "github.com/spf13/pflag" diff --git a/docs/advanced.md b/docs/advanced.md index 9916465c..46a06f31 100644 --- a/docs/advanced.md +++ b/docs/advanced.md @@ -197,9 +197,9 @@ The `target-versions` field in this custom file will set the default target vers Please note that we do not allow overriding anything contained in the default `versions.yaml` that Pluto uses. -## Kube Context +## Kube Context or kubeconfig -When doing helm detection, you may want to use the `--kube-context` to specify a particular context you wish to use in your kubeconfig. +When doing helm or apiVersion detection, you may want to use the `--kube-context` or `--kubeconfig` flags to specify a particular context, or a specific file path, that you wish to use for your kubeconfig. ## Environment Variables From bced21131a8272127873bc0881dc0c3e37ec1ed0 Mon Sep 17 00:00:00 2001 From: bbensky Date: Mon, 22 Jul 2024 12:56:50 -0600 Subject: [PATCH 5/5] adding flag option --- pkg/kube/kube.go | 9 ++++----- pkg/kube/kube_test.go | 14 ++++++++++++++ 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/pkg/kube/kube.go b/pkg/kube/kube.go index cd9e4ab5..902fc05e 100644 --- a/pkg/kube/kube.go +++ b/pkg/kube/kube.go @@ -29,7 +29,7 @@ package kube import ( - "os" + "flag" "sync" "k8s.io/client-go/kubernetes" @@ -81,10 +81,9 @@ func GetConfig(kubeContext string, kubeConfigPath string) (*rest.Config, error) klog.V(3).Infof("using kube context: %s", kubeContext) } - if kubeConfigPath != "" { - klog.V(3).Infof("using kubeconfig at path: %s", kubeConfigPath) - os.Setenv("KUBECONFIG", kubeConfigPath) - } + fs := flag.NewFlagSet("fs", flag.ContinueOnError) + fs.String("kubeconfig", kubeConfigPath, "") + config.RegisterFlags(fs) kubeConfig, err := config.GetConfigWithContext(kubeContext) if err != nil { diff --git a/pkg/kube/kube_test.go b/pkg/kube/kube_test.go index 401ddf2a..9cbb42f9 100644 --- a/pkg/kube/kube_test.go +++ b/pkg/kube/kube_test.go @@ -58,6 +58,20 @@ func Test_getKubeClient(t *testing.T) { kubeConfigPath: "", wantErr: true, }, + { + name: "valid kubeconfig path", + kubeContext: "kind-kind", + kubeConfig: "testdata/kubeconfig_invalid", + kubeConfigPath: "testdata/kubeconfig", + wantErr: false, + }, + { + name: "invalid kubeconfig path", + kubeContext: "kind-kind", + kubeConfig: "testdata/kubeconfig", + kubeConfigPath: "testdata/kubeconfig_invalid", + wantErr: true, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) {