Repository: doitintl/kube-no-trouble
Pull request #86 (2021-01-07 16:54:21)

feat: Support KUBECONFIG env variable
This PR adds support to get kubeconfig path from KUBECONFIG env variable - as per #82.


Patch:
diff --git a/generated/statik/statik.go b/generated/statik/statik.go
index 589fd2c..0970e6a 100644
--- a/generated/statik/statik.go
+++ b/generated/statik/statik.go
@@ -7,6 +7,6 @@ import (
 )
 
 func init() {
-	data := "PK\x03\x04\x14\x00\x08\x00\x08\x00\x0f\x94\x9eQ\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14\x00	\x00deprecated-1-16.regoUT\x05\x00\x01\xbe\xc7\xec_\xacTMk\xdc0\x10=[\xbfbP/Y0n\xddCH\x97n!\x90K)\x84\xd0\x85\xf6\xb0,fb\x8f\x13aY\x12\x96\xect	\xfb\xdf\xcb\xf8c\xe3$\x1bZ\xc2\xde\xec\x997\xf3\xde<i\xe40\xaf\xf0\x8e\xa0 \xd7P\x8e\x81\x8a4=\x17\xa2Fe6\x0d\x85\xb61[x\x14QC\xde\xb6MN\xb0\\\x812\xae\x0d\x9bl+\"t\x8a\x03O\xb5\xd9\x84;\x9b>\x16\\\xcbm\x18\xf8(\xa2H^cMr	\x13 \xa9)`\x81\x01\x13\x835\xc5\"\x8a>\x00C\xbc\xc3\x9c\xa0\xb0\xe4\xc1\xd8\x00\xf7\xd8\x11\x04\x0b\xb7,\xb5T\x86\nP\x06r\xf4\x04\xb6\x04ms\xd4P\xa3Q%\xf9\xe0'\x9a\xbe\x87\\\xc2\x1d\x85\xac\xa0\x12[\x1d\xce^\xf1\xc6 \xcd\x01\x1b\x83\xfc\xda\x9a\x91\xe1\x9b\\\xb0\x1e\xf9C\x99b\xae\xb8R\xa6\xe8\x13\x97N\xfd\xa2\xc6+k\xe4\x12\xd0\xa9\xc4\xea!\xf1\x93\x9c\xc6\x9c~\xabp?f\x0c=\x0c\x99V\xd3\x9a\x82\\\x82\xbc:\xd8\x06\x977\xdf=4T\xdbn\x98+M\xd2s\xd9\xe3\xd7\xca\xf4#p\x0f\xcf\xdf\xb1\x88\xf6b/\xc4Q\xd3\x17\xb0b$\x1b\xfd\xfal\xd0\xa9\xb3f\x10\x0fM\x82\x07\xed\x8b\x17\xed\x187\xa0\xd0\xa9\xac\x1bAO\x9d\x9fC=\x8c\xe7zEN\xdb]M\x86\x87\xe3H$\xadf\xdf6\x92\xfe\x042\xdc\xc5\x7f\xec\xd2[\n\x98\xb2\xd1\xe8\xdc[\xff\x9f\xe56\xee;\x18z`\xab\xc6\x94\x1c\x82~\xf4D\xa6\xc9\x97>\xb4\xef\xad\xba\xa6\xf0`\x9b\xea\xc6j\x95\xef\xfeG\xc3s\x0e3\x94+s\x97T\x17>Q\xf6(\xe1\xc5\x8c\xf0\xc6\x16k\xca\xdbF\x85\xdd{I]_\xf7\xe4\xc2K\xba\xf4\xd3\x8c\xef\n\xa9\xb6f\xb8=\xff\xe49\x81\xa1\xeb\x80\x81\xcaV\x1fc<\xf5\xe1\xf1\xc6\xa8\x1c\xdf5\xdc	\x04\xec\xc5\xab{\xbd\xe1\x1d\xd8\xf2Jo\xb2-\xacV\xf3m8\xacW\x7f\xf3\x07\xa1\xb3t?\xd1@~\xbc\xe9\xf4\x1aLZ\x8e\xa3\x9e\xed\xfb\xfc\x0d\xebP\xc7P\xd1.\x86\x8c\xf7\xb2C\xbd\xa9h\xb7}\x0bT\xa2\xd6\xb7\x98W\x8c\x9d\xbeY9\xbf\xab\x87\xda\xbd\xf8\x1b\x00\x00\xff\xffPK\x07\x08q\xe1s\xb6\x1f\x02\x00\x00\x0b\x06\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x12\x94\x9eQ\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14\x00	\x00deprecated-1-22.regoUT\x05\x00\x01\xc5\xc7\xec_t\x93Q\x8b\x9b@\x10\xc7\x9f\xddO1l_. \xb6\x1e}(\xd2\x14\x0e\xfar\x14J\xe9A\xfb \"\x13\x9d\xe4\x16\xd7]\xd9]M\x8f\x90\xef^F\xa3\xe75\xe9\xdb\xb0\xf3\x9b\x99\xff\xfcG;\xac\x1a<\x10\xd4\xd49\xaa0P\x9d\xde\x7f\x10\xa2EerG\xa1w\xa6\x80\x93\x88\x1cy\xdb\xbb\x8a \xdb\x822]\x1f\xf2\xb2\x10\x11v\x8a\x1f^k\xcb\x99\xbb\x9b\x83\x0d\xd7r\x1b\x06O\"\x8a\xe4wlIf0\x03IK\x01k\x0c\x98\x18l)\x16Q\xf4\x0e\x18\xf1\x1dV\x04\xb5%\x0f\xc6\x06x\xc6\x81 X\xd8\xb1\xd4\xbd2T\x832P\xa1'\xb0{\xd0\xb6B\x0d-\x1a\xb5'\x1f\xfc<f\xec!38P(k\xdac\xaf\xc3\xdd\xd5\xdc\x18\xa4Y\xd8\x18\xe4\xe7\xde\\&|\x91\x1b\xd6#\xbf)S\xaf\x157\xca\xd4c\xe2\xa1S\xbf\xc8ye\x8d\xcc\x00;\x95X=%~R\xa7\xb1\xa2\xdf*<_2\x86\x8eS\xa6\xd7\xf4DAf \xbf.\xb6\xc1\xc3\x8fG\x0f\x8eZ;L{\xa5\xc9\xfd\xbd\x1c\xf9'e\xc6\x15\xb8\x87\xe78\x16\xd1Y\x9c\x85\xb8i\xfa\x06\xb6L\xb2\xd1\xd7\xb7\xc1N\xdd\xb9I<\xb8\x04\x17\xed\x9b\x7f\xda17Q\xd8\xa9r\xb8@\xaf\x9d\xdf\xa2\x1e\xb6p\x92\x8f\xe6\xe0\xc8{\x99M7\xb6\x9a\x0d\xcb%\xfd	d\xb8\xdc\xbf\x1f\xd2\x1d\x05Le1\xaee\xe8\xc8\x16\x18\nG\xeb\x1ae\x0eI\xf3\xc9'\xca.\xd8H\xf9\xcb\xf22M\xd2\x8f\xfct>\x8b\xab\xf99k-\xd8\xfa\xbc,`\xbb]\xab\x16\x8b\x0f+Y\xab\xfcJ\xcb\xed\xae\xf3\xd9f%\xb7\xa97\x87Y\x7fl\x03\xea\x18\x1az\x89\xa1d\x03\x07\xd4yC/\xc5\xff\xa0=j\xbd\xc3\xaaav\x8eY9\xff\x00K\xedY\xfc\x0d\x00\x00\xff\xffPK\x07\x08\xe9\x8a\x04\xd1\xc3\x01\x00\x00\xb4\x03\x00\x00PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x0f\x94\x9eQq\xe1s\xb6\x1f\x02\x00\x00\x0b\x06\x00\x00\x14\x00	\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x00\x00\x00\x00deprecated-1-16.regoUT\x05\x00\x01\xbe\xc7\xec_PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x12\x94\x9eQ\xe9\x8a\x04\xd1\xc3\x01\x00\x00\xb4\x03\x00\x00\x14\x00	\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81j\x02\x00\x00deprecated-1-22.regoUT\x05\x00\x01\xc5\xc7\xec_PK\x05\x06\x00\x00\x00\x00\x02\x00\x02\x00\x96\x00\x00\x00x\x04\x00\x00\x00\x00"
+	data := "PK\x03\x04\x14\x00\x08\x00\x08\x00\xc9\x84'R\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14\x00	\x00deprecated-1-16.regoUT\x05\x00\x01\xfa8\xf7_\xacTMk\xdc0\x10=[\xbfbP/Y0n\xddCH\x97n!\x90K)\x84\xd0\x85\xf6\xb0,fb\x8f\x13aY\x12\x96\xect	\xfb\xdf\xcb\xf8c\xe3$\x1bZ\xc2\xde\xec\x997\xf3\xde<i\xe40\xaf\xf0\x8e\xa0 \xd7P\x8e\x81\x8a4=\x17\xa2Fe6\x0d\x85\xb61[x\x14QC\xde\xb6MN\xb0\\\x812\xae\x0d\x9bl+\"t\x8a\x03O\xb5\xd9\x84;\x9b>\x16\\\xcbm\x18\xf8(\xa2H^cMr	\x13 \xa9)`\x81\x01\x13\x835\xc5\"\x8a>\x00C\xbc\xc3\x9c\xa0\xb0\xe4\xc1\xd8\x00\xf7\xd8\x11\x04\x0b\xb7,\xb5T\x86\nP\x06r\xf4\x04\xb6\x04ms\xd4P\xa3Q%\xf9\xe0'\x9a\xbe\x87\\\xc2\x1d\x85\xac\xa0\x12[\x1d\xce^\xf1\xc6 \xcd\x01\x1b\x83\xfc\xda\x9a\x91\xe1\x9b\\\xb0\x1e\xf9C\x99b\xae\xb8R\xa6\xe8\x13\x97N\xfd\xa2\xc6+k\xe4\x12\xd0\xa9\xc4\xea!\xf1\x93\x9c\xc6\x9c~\xabp?f\x0c=\x0c\x99V\xd3\x9a\x82\\\x82\xbc:\xd8\x06\x977\xdf=4T\xdbn\x98+M\xd2s\xd9\xe3\xd7\xca\xf4#p\x0f\xcf\xdf\xb1\x88\xf6b/\xc4Q\xd3\x17\xb0b$\x1b\xfd\xfal\xd0\xa9\xb3f\x10\x0fM\x82\x07\xed\x8b\x17\xed\x187\xa0\xd0\xa9\xac\x1bAO\x9d\x9fC=\x8c\xe7zEN\xdb]M\x86\x87\xe3H$\xadf\xdf6\x92\xfe\x042\xdc\xc5\x7f\xec\xd2[\n\x98\xb2\xd1\xe8\xdc[\xff\x9f\xe56\xee;\x18z`\xab\xc6\x94\x1c\x82~\xf4D\xa6\xc9\x97>\xb4\xef\xad\xba\xa6\xf0`\x9b\xea\xc6j\x95\xef\xfeG\xc3s\x0e3\x94+s\x97T\x17>Q\xf6(\xe1\xc5\x8c\xf0\xc6\x16k\xca\xdbF\x85\xdd{I]_\xf7\xe4\xc2K\xba\xf4\xd3\x8c\xef\n\xa9\xb6f\xb8=\xff\xe49\x81\xa1\xeb\x80\x81\xcaV\x1fc<\xf5\xe1\xf1\xc6\xa8\x1c\xdf5\xdc	\x04\xec\xc5\xab{\xbd\xe1\x1d\xd8\xf2Jo\xb2-\xacV\xf3m8\xacW\x7f\xf3\x07\xa1\xb3t?\xd1@~\xbc\xe9\xf4\x1aLZ\x8e\xa3\x9e\xed\xfb\xfc\x0d\xebP\xc7P\xd1.\x86\x8c\xf7\xb2C\xbd\xa9h\xb7}\x0bT\xa2\xd6\xb7\x98W\x8c\x9d\xbeY9\xbf\xab\x87\xda\xbd\xf8\x1b\x00\x00\xff\xffPK\x07\x08q\xe1s\xb6\x1f\x02\x00\x00\x0b\x06\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\xc9\x84'R\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14\x00	\x00deprecated-1-22.regoUT\x05\x00\x01\xfa8\xf7_t\x93Q\x8b\x9b@\x10\xc7\x9f\xddO1l_. \xb6\x1e}(\xd2\x14\x0e\xfar\x14J\xe9A\xfb \"\x13\x9d\xe4\x16\xd7]\xd9]M\x8f\x90\xef^F\xa3\xe75\xe9\xdb\xb0\xf3\x9b\x99\xff\xfcG;\xac\x1a<\x10\xd4\xd49\xaa0P\x9d\xde\x7f\x10\xa2EerG\xa1w\xa6\x80\x93\x88\x1cy\xdb\xbb\x8a \xdb\x822]\x1f\xf2\xb2\x10\x11v\x8a\x1f^k\xcb\x99\xbb\x9b\x83\x0d\xd7r\x1b\x06O\"\x8a\xe4wlIf0\x03IK\x01k\x0c\x98\x18l)\x16Q\xf4\x0e\x18\xf1\x1dV\x04\xb5%\x0f\xc6\x06x\xc6\x81 X\xd8\xb1\xd4\xbd2T\x832P\xa1'\xb0{\xd0\xb6B\x0d-\x1a\xb5'\x1f\xfc<f\xec!38P(k\xdac\xaf\xc3\xdd\xd5\xdc\x18\xa4Y\xd8\x18\xe4\xe7\xde\\&|\x91\x1b\xd6#\xbf)S\xaf\x157\xca\xd4c\xe2\xa1S\xbf\xc8ye\x8d\xcc\x00;\x95X=%~R\xa7\xb1\xa2\xdf*<_2\x86\x8eS\xa6\xd7\xf4DAf \xbf.\xb6\xc1\xc3\x8fG\x0f\x8eZ;L{\xa5\xc9\xfd\xbd\x1c\xf9'e\xc6\x15\xb8\x87\xe78\x16\xd1Y\x9c\x85\xb8i\xfa\x06\xb6L\xb2\xd1\xd7\xb7\xc1N\xdd\xb9I<\xb8\x04\x17\xed\x9b\x7f\xda17Q\xd8\xa9r\xb8@\xaf\x9d\xdf\xa2\x1e\xb6p\x92\x8f\xe6\xe0\xc8{\x99M7\xb6\x9a\x0d\xcb%\xfd	d\xb8\xdc\xbf\x1f\xd2\x1d\x05Le1\xaee\xe8\xc8\x16\x18\nG\xeb\x1ae\x0eI\xf3\xc9'\xca.\xd8H\xf9\xcb\xf22M\xd2\x8f\xfct>\x8b\xab\xf99k-\xd8\xfa\xbc,`\xbb]\xab\x16\x8b\x0f+Y\xab\xfcJ\xcb\xed\xae\xf3\xd9f%\xb7\xa97\x87Y\x7fl\x03\xea\x18\x1az\x89\xa1d\x03\x07\xd4yC/\xc5\xff\xa0=j\xbd\xc3\xaaav\x8eY9\xff\x00K\xedY\xfc\x0d\x00\x00\xff\xffPK\x07\x08\xe9\x8a\x04\xd1\xc3\x01\x00\x00\xb4\x03\x00\x00PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\xc9\x84'Rq\xe1s\xb6\x1f\x02\x00\x00\x0b\x06\x00\x00\x14\x00	\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x00\x00\x00\x00deprecated-1-16.regoUT\x05\x00\x01\xfa8\xf7_PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\xc9\x84'R\xe9\x8a\x04\xd1\xc3\x01\x00\x00\xb4\x03\x00\x00\x14\x00	\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81j\x02\x00\x00deprecated-1-22.regoUT\x05\x00\x01\xfa8\xf7_PK\x05\x06\x00\x00\x00\x00\x02\x00\x02\x00\x96\x00\x00\x00x\x04\x00\x00\x00\x00"
 	fs.Register(data)
 }
diff --git a/pkg/config/config.go b/pkg/config/config.go
index 6da831a..4c6a4f0 100644
--- a/pkg/config/config.go
+++ b/pkg/config/config.go
@@ -1,6 +1,7 @@
 package config
 
 import (
+	"os"
 	"path/filepath"
 
 	flag "github.com/spf13/pflag"
@@ -28,10 +29,18 @@ func NewFromFlags() (*Config, error) {
 	flag.BoolVar(&config.Helm2, "helm2", true, "enable Helm v2 collector")
 	flag.BoolVar(&config.Helm3, "helm3", true, "enable Helm v3 collector")
 	flag.StringSliceVarP(&config.Filenames, "filename", "f", []string{}, "manifests to check, use - for stdin")
-	flag.StringVarP(&config.Kubeconfig, "kubeconfig", "k", filepath.Join(home, ".kube", "config"), "path to the kubeconfig file")
+	flag.StringVarP(&config.Kubeconfig, "kubeconfig", "k", envOrString("KUBECONFIG", filepath.Join(home, ".kube", "config")), "path to the kubeconfig file")
 	flag.StringVarP(&config.Output, "output", "o", "text", "output format - [text|json]")
 
 	flag.Parse()
 
 	return &config, nil
 }
+
+func envOrString(env string, def string) string {
+	val, ok := os.LookupEnv(env)
+	if ok {
+		return val
+	}
+	return def
+}


Test patch:
diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go
index 72d0f36..58b046b 100644
--- a/pkg/config/config_test.go
+++ b/pkg/config/config_test.go
@@ -1,17 +1,91 @@
 package config
 
 import (
+	"github.com/spf13/pflag"
+	"k8s.io/client-go/util/homedir"
+	"os"
 	"testing"
 )
 
-func TestParseConfigFromFlags(t *testing.T) {
+func TestNewFromFlags(t *testing.T) {
+	// reset for testing
+	pflag.CommandLine = pflag.NewFlagSet(os.Args[0], pflag.ExitOnError)
+
 	config, err := NewFromFlags()
 
-	if err != nil && config == nil {
-		t.Errorf("Formatting flags failed %s", err)
+	if err != nil {
+		t.Errorf("Flags parsing failed %s", err)
 	}
 
 	if !config.Cluster && config.Output != "text" {
 		t.Errorf("Config not parsed correctly")
 	}
 }
+
+func TestNewFromFlagsKubeconfigEnv(t *testing.T) {
+	// reset for testing
+	pflag.CommandLine = pflag.NewFlagSet(os.Args[0], pflag.ExitOnError)
+
+	testVal := "my-file.conf"
+
+	err := os.Setenv("KUBECONFIG", testVal)
+	if err != nil {
+		t.Errorf("failed to set env variable: %s", err)
+	}
+
+	config, err := NewFromFlags()
+
+	if err != nil {
+		t.Errorf("Formatting flags failed %s", err)
+	}
+
+	if config.Kubeconfig != testVal {
+		t.Errorf("kubeconfig option not loaded correctly from ebv variable, expected: %s, got: %s", testVal, config.Kubeconfig)
+	}
+}
+
+func TestNewFromFlagsKubeconfigHome(t *testing.T) {
+	// reset for testing
+	pflag.CommandLine = pflag.NewFlagSet(os.Args[0], pflag.ExitOnError)
+
+	expected := homedir.HomeDir() + "/.kube/config"
+
+	err := os.Unsetenv("KUBECONFIG")
+	if err != nil {
+		t.Errorf("failed to unset KUBECONFIG env variable: %s", err)
+	}
+
+	config, err := NewFromFlags()
+
+	if err != nil {
+		t.Errorf("Formatting flags failed %s", err)
+	}
+
+	if config.Kubeconfig != expected {
+		t.Errorf("kubeconfig option not set to expected default, expected: %s, got: %s", expected, config.Kubeconfig)
+	}
+}
+
+func TestEnvOrStringVariable(t *testing.T) {
+	err := os.Setenv("FOO", "1")
+	if err != nil {
+		t.Errorf("failed to set env variable: %e", err)
+	}
+
+	i := envOrString("FOO", "default")
+	if i != "1" {
+		t.Errorf("Expected to get env variable, got %s insteadt", i)
+	}
+}
+
+func TestEnvOrStringDefault(t *testing.T) {
+	err := os.Unsetenv("FOO")
+	if err != nil {
+		t.Errorf("failed to unset env variable: %e", err)
+	}
+
+	i := envOrString("FOO", "default")
+	if i != "default" {
+		t.Errorf("Expected to get default string, got %s instead", i)
+	}
+}