From b9294aa56453eb654f1a57d89f462aeb8b1c0d64 Mon Sep 17 00:00:00 2001 From: Mateusz Gozdek Date: Tue, 9 Jun 2020 20:16:54 +0200 Subject: [PATCH 1/5] cli/cmd: rename --kubeconfig flag to --kubeconfig-file This also renames environment variable equivalent of old flag, which was KUBECONFIG to KUBECONFIG_FILE. This is to avoid prefering KUBECONFIG environment variable over cluster configuration, which is happening right now, as we treat --kubeconfig flag and KUBECONFIG environment variable as the same thing, implicitly via 'viper.AutomaticEnv()' call. The order of selecting kubeconfig file to use should be following: 1. --kubeconfig-file flag OR KUBECONFIG_FILE environment variable 2. cluster configuration in working directory 3. KUBECONFIG environment variable (currently not implemented) 4. ~/.kube/config file Part of #595. Signed-off-by: Mateusz Gozdek --- cli/cmd/root.go | 10 +++++++--- cli/cmd/utils.go | 2 +- docs/cli/lokoctl.md | 8 ++++---- docs/cli/lokoctl_cluster.md | 6 +++--- docs/cli/lokoctl_cluster_apply.md | 6 +++--- docs/cli/lokoctl_cluster_destroy.md | 6 +++--- docs/cli/lokoctl_component.md | 6 +++--- docs/cli/lokoctl_component_apply.md | 6 +++--- docs/cli/lokoctl_component_delete.md | 6 +++--- docs/cli/lokoctl_component_list.md | 6 +++--- docs/cli/lokoctl_component_render-manifest.md | 6 +++--- docs/cli/lokoctl_health.md | 6 +++--- docs/cli/lokoctl_version.md | 6 +++--- 13 files changed, 42 insertions(+), 38 deletions(-) diff --git a/cli/cmd/root.go b/cli/cmd/root.go index 8000e3dbb..f1dbef092 100644 --- a/cli/cmd/root.go +++ b/cli/cmd/root.go @@ -43,6 +43,10 @@ func Execute() { } } +const ( + kubeconfigFlag = "kubeconfig-file" +) + func init() { cobra.OnInitialize(cobraInit) @@ -50,10 +54,10 @@ func init() { // Add kubeconfig flag. RootCmd.PersistentFlags().String( - "kubeconfig", + kubeconfigFlag, "", // Special empty default, use getKubeconfig() - "Path to kubeconfig file, taken from the asset dir if not given, and finally falls back to ~/.kube/config") - viper.BindPFlag("kubeconfig", RootCmd.PersistentFlags().Lookup("kubeconfig")) + "Path to kubeconfig file, taken from the asset dir if not given and finally falls back to ~/.kube/config") + viper.BindPFlag(kubeconfigFlag, RootCmd.PersistentFlags().Lookup(kubeconfigFlag)) RootCmd.PersistentFlags().String("lokocfg", "./", "Path to lokocfg directory or file") viper.BindPFlag("lokocfg", RootCmd.PersistentFlags().Lookup("lokocfg")) diff --git a/cli/cmd/utils.go b/cli/cmd/utils.go index 9ed5dfc33..ff7455566 100644 --- a/cli/cmd/utils.go +++ b/cli/cmd/utils.go @@ -106,7 +106,7 @@ func expandKubeconfigPath(path string) string { // and finally the global default value is used. This cannot be done in Viper // because we need the other values from Viper to find the asset directory. func getKubeconfig() (string, error) { - kubeconfig := viper.GetString("kubeconfig") + kubeconfig := viper.GetString(kubeconfigFlag) if kubeconfig != "" { return expandKubeconfigPath(kubeconfig), nil } diff --git a/docs/cli/lokoctl.md b/docs/cli/lokoctl.md index dab08c260..96b5c2d9a 100644 --- a/docs/cli/lokoctl.md +++ b/docs/cli/lokoctl.md @@ -9,10 +9,10 @@ Manage Lokomotive clusters ### Options ``` - -h, --help help for lokoctl - --kubeconfig string Path to kubeconfig file, taken from the asset dir if not given, and finally falls back to ~/.kube/config - --lokocfg string Path to lokocfg directory or file (default "./") - --lokocfg-vars string Path to lokocfg.vars file (default "./lokocfg.vars") + -h, --help help for lokoctl + --kubeconfig-file string Path to kubeconfig file, taken from the asset dir if not given and finally falls back to ~/.kube/config + --lokocfg string Path to lokocfg directory or file (default "./") + --lokocfg-vars string Path to lokocfg.vars file (default "./lokocfg.vars") ``` ### SEE ALSO diff --git a/docs/cli/lokoctl_cluster.md b/docs/cli/lokoctl_cluster.md index 07a855cdb..b10ab0410 100644 --- a/docs/cli/lokoctl_cluster.md +++ b/docs/cli/lokoctl_cluster.md @@ -15,9 +15,9 @@ Manage a cluster ### Options inherited from parent commands ``` - --kubeconfig string Path to kubeconfig file, taken from the asset dir if not given, and finally falls back to ~/.kube/config - --lokocfg string Path to lokocfg directory or file (default "./") - --lokocfg-vars string Path to lokocfg.vars file (default "./lokocfg.vars") + --kubeconfig-file string Path to kubeconfig file, taken from the asset dir if not given and finally falls back to ~/.kube/config + --lokocfg string Path to lokocfg directory or file (default "./") + --lokocfg-vars string Path to lokocfg.vars file (default "./lokocfg.vars") ``` ### SEE ALSO diff --git a/docs/cli/lokoctl_cluster_apply.md b/docs/cli/lokoctl_cluster_apply.md index 8dab63bdf..c0bec8171 100644 --- a/docs/cli/lokoctl_cluster_apply.md +++ b/docs/cli/lokoctl_cluster_apply.md @@ -25,9 +25,9 @@ lokoctl cluster apply [flags] ### Options inherited from parent commands ``` - --kubeconfig string Path to kubeconfig file, taken from the asset dir if not given, and finally falls back to ~/.kube/config - --lokocfg string Path to lokocfg directory or file (default "./") - --lokocfg-vars string Path to lokocfg.vars file (default "./lokocfg.vars") + --kubeconfig-file string Path to kubeconfig file, taken from the asset dir if not given and finally falls back to ~/.kube/config + --lokocfg string Path to lokocfg directory or file (default "./") + --lokocfg-vars string Path to lokocfg.vars file (default "./lokocfg.vars") ``` ### SEE ALSO diff --git a/docs/cli/lokoctl_cluster_destroy.md b/docs/cli/lokoctl_cluster_destroy.md index 1b3413b64..180dc8577 100644 --- a/docs/cli/lokoctl_cluster_destroy.md +++ b/docs/cli/lokoctl_cluster_destroy.md @@ -21,9 +21,9 @@ lokoctl cluster destroy [flags] ### Options inherited from parent commands ``` - --kubeconfig string Path to kubeconfig file, taken from the asset dir if not given, and finally falls back to ~/.kube/config - --lokocfg string Path to lokocfg directory or file (default "./") - --lokocfg-vars string Path to lokocfg.vars file (default "./lokocfg.vars") + --kubeconfig-file string Path to kubeconfig file, taken from the asset dir if not given and finally falls back to ~/.kube/config + --lokocfg string Path to lokocfg directory or file (default "./") + --lokocfg-vars string Path to lokocfg.vars file (default "./lokocfg.vars") ``` ### SEE ALSO diff --git a/docs/cli/lokoctl_component.md b/docs/cli/lokoctl_component.md index 9447cf9b3..2a4160988 100644 --- a/docs/cli/lokoctl_component.md +++ b/docs/cli/lokoctl_component.md @@ -15,9 +15,9 @@ Manage components ### Options inherited from parent commands ``` - --kubeconfig string Path to kubeconfig file, taken from the asset dir if not given, and finally falls back to ~/.kube/config - --lokocfg string Path to lokocfg directory or file (default "./") - --lokocfg-vars string Path to lokocfg.vars file (default "./lokocfg.vars") + --kubeconfig-file string Path to kubeconfig file, taken from the asset dir if not given and finally falls back to ~/.kube/config + --lokocfg string Path to lokocfg directory or file (default "./") + --lokocfg-vars string Path to lokocfg.vars file (default "./lokocfg.vars") ``` ### SEE ALSO diff --git a/docs/cli/lokoctl_component_apply.md b/docs/cli/lokoctl_component_apply.md index b60eed8d4..21b5a8ea2 100644 --- a/docs/cli/lokoctl_component_apply.md +++ b/docs/cli/lokoctl_component_apply.md @@ -21,9 +21,9 @@ lokoctl component apply [flags] ### Options inherited from parent commands ``` - --kubeconfig string Path to kubeconfig file, taken from the asset dir if not given, and finally falls back to ~/.kube/config - --lokocfg string Path to lokocfg directory or file (default "./") - --lokocfg-vars string Path to lokocfg.vars file (default "./lokocfg.vars") + --kubeconfig-file string Path to kubeconfig file, taken from the asset dir if not given and finally falls back to ~/.kube/config + --lokocfg string Path to lokocfg directory or file (default "./") + --lokocfg-vars string Path to lokocfg.vars file (default "./lokocfg.vars") ``` ### SEE ALSO diff --git a/docs/cli/lokoctl_component_delete.md b/docs/cli/lokoctl_component_delete.md index 955f09c2a..279746bc7 100644 --- a/docs/cli/lokoctl_component_delete.md +++ b/docs/cli/lokoctl_component_delete.md @@ -22,9 +22,9 @@ lokoctl component delete [flags] ### Options inherited from parent commands ``` - --kubeconfig string Path to kubeconfig file, taken from the asset dir if not given, and finally falls back to ~/.kube/config - --lokocfg string Path to lokocfg directory or file (default "./") - --lokocfg-vars string Path to lokocfg.vars file (default "./lokocfg.vars") + --kubeconfig-file string Path to kubeconfig file, taken from the asset dir if not given and finally falls back to ~/.kube/config + --lokocfg string Path to lokocfg directory or file (default "./") + --lokocfg-vars string Path to lokocfg.vars file (default "./lokocfg.vars") ``` ### SEE ALSO diff --git a/docs/cli/lokoctl_component_list.md b/docs/cli/lokoctl_component_list.md index 6b5ca04f5..fd72622aa 100644 --- a/docs/cli/lokoctl_component_list.md +++ b/docs/cli/lokoctl_component_list.md @@ -19,9 +19,9 @@ lokoctl component list [flags] ### Options inherited from parent commands ``` - --kubeconfig string Path to kubeconfig file, taken from the asset dir if not given, and finally falls back to ~/.kube/config - --lokocfg string Path to lokocfg directory or file (default "./") - --lokocfg-vars string Path to lokocfg.vars file (default "./lokocfg.vars") + --kubeconfig-file string Path to kubeconfig file, taken from the asset dir if not given and finally falls back to ~/.kube/config + --lokocfg string Path to lokocfg directory or file (default "./") + --lokocfg-vars string Path to lokocfg.vars file (default "./lokocfg.vars") ``` ### SEE ALSO diff --git a/docs/cli/lokoctl_component_render-manifest.md b/docs/cli/lokoctl_component_render-manifest.md index 7226baf1c..e50095f68 100644 --- a/docs/cli/lokoctl_component_render-manifest.md +++ b/docs/cli/lokoctl_component_render-manifest.md @@ -19,9 +19,9 @@ lokoctl component render-manifest [flags] ### Options inherited from parent commands ``` - --kubeconfig string Path to kubeconfig file, taken from the asset dir if not given, and finally falls back to ~/.kube/config - --lokocfg string Path to lokocfg directory or file (default "./") - --lokocfg-vars string Path to lokocfg.vars file (default "./lokocfg.vars") + --kubeconfig-file string Path to kubeconfig file, taken from the asset dir if not given and finally falls back to ~/.kube/config + --lokocfg string Path to lokocfg directory or file (default "./") + --lokocfg-vars string Path to lokocfg.vars file (default "./lokocfg.vars") ``` ### SEE ALSO diff --git a/docs/cli/lokoctl_health.md b/docs/cli/lokoctl_health.md index 2a883a042..6ac897fdc 100644 --- a/docs/cli/lokoctl_health.md +++ b/docs/cli/lokoctl_health.md @@ -19,9 +19,9 @@ lokoctl health [flags] ### Options inherited from parent commands ``` - --kubeconfig string Path to kubeconfig file, taken from the asset dir if not given, and finally falls back to ~/.kube/config - --lokocfg string Path to lokocfg directory or file (default "./") - --lokocfg-vars string Path to lokocfg.vars file (default "./lokocfg.vars") + --kubeconfig-file string Path to kubeconfig file, taken from the asset dir if not given and finally falls back to ~/.kube/config + --lokocfg string Path to lokocfg directory or file (default "./") + --lokocfg-vars string Path to lokocfg.vars file (default "./lokocfg.vars") ``` ### SEE ALSO diff --git a/docs/cli/lokoctl_version.md b/docs/cli/lokoctl_version.md index 9429a8682..6bf4b4c0e 100644 --- a/docs/cli/lokoctl_version.md +++ b/docs/cli/lokoctl_version.md @@ -19,9 +19,9 @@ lokoctl version [flags] ### Options inherited from parent commands ``` - --kubeconfig string Path to kubeconfig file, taken from the asset dir if not given, and finally falls back to ~/.kube/config - --lokocfg string Path to lokocfg directory or file (default "./") - --lokocfg-vars string Path to lokocfg.vars file (default "./lokocfg.vars") + --kubeconfig-file string Path to kubeconfig file, taken from the asset dir if not given and finally falls back to ~/.kube/config + --lokocfg string Path to lokocfg directory or file (default "./") + --lokocfg-vars string Path to lokocfg.vars file (default "./lokocfg.vars") ``` ### SEE ALSO From 97469abbebe7d7c73cf2d40d4a5722ae324bd395 Mon Sep 17 00:00:00 2001 From: Mateusz Gozdek Date: Tue, 9 Jun 2020 20:29:22 +0200 Subject: [PATCH 2/5] cli/cmd: add back support for using KUBECONFIG env variable After renaming --kubeconfig flag to --kubeconfig-file, we lost ability to use kubeconfig file defined by KUBECONFIG environment variable for installing components. This commit adds back this functionality and improves the code of getKubeconfig() function a bit. Closes #595 Signed-off-by: Mateusz Gozdek --- cli/cmd/root.go | 5 +++- cli/cmd/utils.go | 29 ++++++++++++++----- docs/cli/lokoctl.md | 2 +- docs/cli/lokoctl_cluster.md | 2 +- docs/cli/lokoctl_cluster_apply.md | 2 +- docs/cli/lokoctl_cluster_destroy.md | 2 +- docs/cli/lokoctl_component.md | 2 +- docs/cli/lokoctl_component_apply.md | 2 +- docs/cli/lokoctl_component_delete.md | 2 +- docs/cli/lokoctl_component_list.md | 2 +- docs/cli/lokoctl_component_render-manifest.md | 2 +- docs/cli/lokoctl_health.md | 2 +- docs/cli/lokoctl_version.md | 2 +- 13 files changed, 37 insertions(+), 19 deletions(-) diff --git a/cli/cmd/root.go b/cli/cmd/root.go index f1dbef092..d8f1d5de2 100644 --- a/cli/cmd/root.go +++ b/cli/cmd/root.go @@ -56,7 +56,10 @@ func init() { RootCmd.PersistentFlags().String( kubeconfigFlag, "", // Special empty default, use getKubeconfig() - "Path to kubeconfig file, taken from the asset dir if not given and finally falls back to ~/.kube/config") + `Path to a kubeconfig file. If empty, the following precedence order is `+ + `used: 1. cluster asset dir when a lokocfg file is present in the `+ + `current directory 2. KUBECONFIG environment variable 3. `+ + `"~/.kube/config"`) viper.BindPFlag(kubeconfigFlag, RootCmd.PersistentFlags().Lookup(kubeconfigFlag)) RootCmd.PersistentFlags().String("lokocfg", "./", "Path to lokocfg directory or file") diff --git a/cli/cmd/utils.go b/cli/cmd/utils.go index ff7455566..d92994fbd 100644 --- a/cli/cmd/utils.go +++ b/cli/cmd/utils.go @@ -29,6 +29,11 @@ import ( "github.com/kinvolk/lokomotive/pkg/platform" ) +const ( + kubeconfigEnvVariable = "KUBECONFIG" + defaultKubeconfigPath = "~/.kube/config" +) + // getConfiguredBackend loads a backend from the given configuration file. func getConfiguredBackend(lokoConfig *config.Config) (backend.Backend, hcl.Diagnostics) { if lokoConfig.RootConfig.Backend == nil { @@ -101,10 +106,13 @@ func expandKubeconfigPath(path string) string { return path } -// getKubeconfig finds the kubeconfig to be used. Precedence takes a specified -// flag or environment variable. Then the asset directory of the cluster is searched -// and finally the global default value is used. This cannot be done in Viper -// because we need the other values from Viper to find the asset directory. +// getKubeconfig finds the kubeconfig to be used. The precedence is the following: +// - --kubeconfig-file flag OR KUBECONFIG_FILE environent variable (the latter +// is a side-effect of cobra/viper and should NOT be documented because it's +// confusing). +// - Asset directory from cluster configuration. +// - KUBECONFIG environment variable. +// - ~/.kube/config path, which is the default for kubectl. func getKubeconfig() (string, error) { kubeconfig := viper.GetString(kubeconfigFlag) if kubeconfig != "" { @@ -116,11 +124,18 @@ func getKubeconfig() (string, error) { return "", err } - if assetDir != "" { - return expandKubeconfigPath(assetsKubeconfig(assetDir)), nil + paths := []string{ + assetDir, + os.Getenv(kubeconfigEnvVariable), + } + + for _, path := range paths { + if path != "" { + return expandKubeconfigPath(path), nil + } } - return expandKubeconfigPath("~/.kube/config"), nil + return expandKubeconfigPath(defaultKubeconfigPath), nil } func assetsKubeconfig(assetDir string) string { diff --git a/docs/cli/lokoctl.md b/docs/cli/lokoctl.md index 96b5c2d9a..ea599934c 100644 --- a/docs/cli/lokoctl.md +++ b/docs/cli/lokoctl.md @@ -10,7 +10,7 @@ Manage Lokomotive clusters ``` -h, --help help for lokoctl - --kubeconfig-file string Path to kubeconfig file, taken from the asset dir if not given and finally falls back to ~/.kube/config + --kubeconfig-file string Path to a kubeconfig file. If empty, the following precedence order is used: 1. cluster asset dir when a lokocfg file is present in the current directory 2. KUBECONFIG environment variable 3. "~/.kube/config" --lokocfg string Path to lokocfg directory or file (default "./") --lokocfg-vars string Path to lokocfg.vars file (default "./lokocfg.vars") ``` diff --git a/docs/cli/lokoctl_cluster.md b/docs/cli/lokoctl_cluster.md index b10ab0410..3bf7177bb 100644 --- a/docs/cli/lokoctl_cluster.md +++ b/docs/cli/lokoctl_cluster.md @@ -15,7 +15,7 @@ Manage a cluster ### Options inherited from parent commands ``` - --kubeconfig-file string Path to kubeconfig file, taken from the asset dir if not given and finally falls back to ~/.kube/config + --kubeconfig-file string Path to a kubeconfig file. If empty, the following precedence order is used: 1. cluster asset dir when a lokocfg file is present in the current directory 2. KUBECONFIG environment variable 3. "~/.kube/config" --lokocfg string Path to lokocfg directory or file (default "./") --lokocfg-vars string Path to lokocfg.vars file (default "./lokocfg.vars") ``` diff --git a/docs/cli/lokoctl_cluster_apply.md b/docs/cli/lokoctl_cluster_apply.md index c0bec8171..1cabc87c8 100644 --- a/docs/cli/lokoctl_cluster_apply.md +++ b/docs/cli/lokoctl_cluster_apply.md @@ -25,7 +25,7 @@ lokoctl cluster apply [flags] ### Options inherited from parent commands ``` - --kubeconfig-file string Path to kubeconfig file, taken from the asset dir if not given and finally falls back to ~/.kube/config + --kubeconfig-file string Path to a kubeconfig file. If empty, the following precedence order is used: 1. cluster asset dir when a lokocfg file is present in the current directory 2. KUBECONFIG environment variable 3. "~/.kube/config" --lokocfg string Path to lokocfg directory or file (default "./") --lokocfg-vars string Path to lokocfg.vars file (default "./lokocfg.vars") ``` diff --git a/docs/cli/lokoctl_cluster_destroy.md b/docs/cli/lokoctl_cluster_destroy.md index 180dc8577..c097c7529 100644 --- a/docs/cli/lokoctl_cluster_destroy.md +++ b/docs/cli/lokoctl_cluster_destroy.md @@ -21,7 +21,7 @@ lokoctl cluster destroy [flags] ### Options inherited from parent commands ``` - --kubeconfig-file string Path to kubeconfig file, taken from the asset dir if not given and finally falls back to ~/.kube/config + --kubeconfig-file string Path to a kubeconfig file. If empty, the following precedence order is used: 1. cluster asset dir when a lokocfg file is present in the current directory 2. KUBECONFIG environment variable 3. "~/.kube/config" --lokocfg string Path to lokocfg directory or file (default "./") --lokocfg-vars string Path to lokocfg.vars file (default "./lokocfg.vars") ``` diff --git a/docs/cli/lokoctl_component.md b/docs/cli/lokoctl_component.md index 2a4160988..ea3b04e14 100644 --- a/docs/cli/lokoctl_component.md +++ b/docs/cli/lokoctl_component.md @@ -15,7 +15,7 @@ Manage components ### Options inherited from parent commands ``` - --kubeconfig-file string Path to kubeconfig file, taken from the asset dir if not given and finally falls back to ~/.kube/config + --kubeconfig-file string Path to a kubeconfig file. If empty, the following precedence order is used: 1. cluster asset dir when a lokocfg file is present in the current directory 2. KUBECONFIG environment variable 3. "~/.kube/config" --lokocfg string Path to lokocfg directory or file (default "./") --lokocfg-vars string Path to lokocfg.vars file (default "./lokocfg.vars") ``` diff --git a/docs/cli/lokoctl_component_apply.md b/docs/cli/lokoctl_component_apply.md index 21b5a8ea2..dd1de1311 100644 --- a/docs/cli/lokoctl_component_apply.md +++ b/docs/cli/lokoctl_component_apply.md @@ -21,7 +21,7 @@ lokoctl component apply [flags] ### Options inherited from parent commands ``` - --kubeconfig-file string Path to kubeconfig file, taken from the asset dir if not given and finally falls back to ~/.kube/config + --kubeconfig-file string Path to a kubeconfig file. If empty, the following precedence order is used: 1. cluster asset dir when a lokocfg file is present in the current directory 2. KUBECONFIG environment variable 3. "~/.kube/config" --lokocfg string Path to lokocfg directory or file (default "./") --lokocfg-vars string Path to lokocfg.vars file (default "./lokocfg.vars") ``` diff --git a/docs/cli/lokoctl_component_delete.md b/docs/cli/lokoctl_component_delete.md index 279746bc7..819db5cc3 100644 --- a/docs/cli/lokoctl_component_delete.md +++ b/docs/cli/lokoctl_component_delete.md @@ -22,7 +22,7 @@ lokoctl component delete [flags] ### Options inherited from parent commands ``` - --kubeconfig-file string Path to kubeconfig file, taken from the asset dir if not given and finally falls back to ~/.kube/config + --kubeconfig-file string Path to a kubeconfig file. If empty, the following precedence order is used: 1. cluster asset dir when a lokocfg file is present in the current directory 2. KUBECONFIG environment variable 3. "~/.kube/config" --lokocfg string Path to lokocfg directory or file (default "./") --lokocfg-vars string Path to lokocfg.vars file (default "./lokocfg.vars") ``` diff --git a/docs/cli/lokoctl_component_list.md b/docs/cli/lokoctl_component_list.md index fd72622aa..31b5b9885 100644 --- a/docs/cli/lokoctl_component_list.md +++ b/docs/cli/lokoctl_component_list.md @@ -19,7 +19,7 @@ lokoctl component list [flags] ### Options inherited from parent commands ``` - --kubeconfig-file string Path to kubeconfig file, taken from the asset dir if not given and finally falls back to ~/.kube/config + --kubeconfig-file string Path to a kubeconfig file. If empty, the following precedence order is used: 1. cluster asset dir when a lokocfg file is present in the current directory 2. KUBECONFIG environment variable 3. "~/.kube/config" --lokocfg string Path to lokocfg directory or file (default "./") --lokocfg-vars string Path to lokocfg.vars file (default "./lokocfg.vars") ``` diff --git a/docs/cli/lokoctl_component_render-manifest.md b/docs/cli/lokoctl_component_render-manifest.md index e50095f68..63e343993 100644 --- a/docs/cli/lokoctl_component_render-manifest.md +++ b/docs/cli/lokoctl_component_render-manifest.md @@ -19,7 +19,7 @@ lokoctl component render-manifest [flags] ### Options inherited from parent commands ``` - --kubeconfig-file string Path to kubeconfig file, taken from the asset dir if not given and finally falls back to ~/.kube/config + --kubeconfig-file string Path to a kubeconfig file. If empty, the following precedence order is used: 1. cluster asset dir when a lokocfg file is present in the current directory 2. KUBECONFIG environment variable 3. "~/.kube/config" --lokocfg string Path to lokocfg directory or file (default "./") --lokocfg-vars string Path to lokocfg.vars file (default "./lokocfg.vars") ``` diff --git a/docs/cli/lokoctl_health.md b/docs/cli/lokoctl_health.md index 6ac897fdc..169d4ca26 100644 --- a/docs/cli/lokoctl_health.md +++ b/docs/cli/lokoctl_health.md @@ -19,7 +19,7 @@ lokoctl health [flags] ### Options inherited from parent commands ``` - --kubeconfig-file string Path to kubeconfig file, taken from the asset dir if not given and finally falls back to ~/.kube/config + --kubeconfig-file string Path to a kubeconfig file. If empty, the following precedence order is used: 1. cluster asset dir when a lokocfg file is present in the current directory 2. KUBECONFIG environment variable 3. "~/.kube/config" --lokocfg string Path to lokocfg directory or file (default "./") --lokocfg-vars string Path to lokocfg.vars file (default "./lokocfg.vars") ``` diff --git a/docs/cli/lokoctl_version.md b/docs/cli/lokoctl_version.md index 6bf4b4c0e..7169d4688 100644 --- a/docs/cli/lokoctl_version.md +++ b/docs/cli/lokoctl_version.md @@ -19,7 +19,7 @@ lokoctl version [flags] ### Options inherited from parent commands ``` - --kubeconfig-file string Path to kubeconfig file, taken from the asset dir if not given and finally falls back to ~/.kube/config + --kubeconfig-file string Path to a kubeconfig file. If empty, the following precedence order is used: 1. cluster asset dir when a lokocfg file is present in the current directory 2. KUBECONFIG environment variable 3. "~/.kube/config" --lokocfg string Path to lokocfg directory or file (default "./") --lokocfg-vars string Path to lokocfg.vars file (default "./lokocfg.vars") ``` From 5024bf774f0606cd80a347cc23f5da6f1270bc14 Mon Sep 17 00:00:00 2001 From: Mateusz Gozdek Date: Tue, 9 Jun 2020 23:52:03 +0200 Subject: [PATCH 3/5] cli/cmd/root.go: handle binding flag errors Otherwise linter complains. Signed-off-by: Mateusz Gozdek --- cli/cmd/root.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cli/cmd/root.go b/cli/cmd/root.go index d8f1d5de2..2fd922907 100644 --- a/cli/cmd/root.go +++ b/cli/cmd/root.go @@ -60,7 +60,10 @@ func init() { `used: 1. cluster asset dir when a lokocfg file is present in the `+ `current directory 2. KUBECONFIG environment variable 3. `+ `"~/.kube/config"`) - viper.BindPFlag(kubeconfigFlag, RootCmd.PersistentFlags().Lookup(kubeconfigFlag)) + + if err := viper.BindPFlag(kubeconfigFlag, RootCmd.PersistentFlags().Lookup(kubeconfigFlag)); err != nil { + panic("failed registering kubeconfig flag") + } RootCmd.PersistentFlags().String("lokocfg", "./", "Path to lokocfg directory or file") viper.BindPFlag("lokocfg", RootCmd.PersistentFlags().Lookup("lokocfg")) From c61ba209e1ff1def905fb420be57e4c525d154b4 Mon Sep 17 00:00:00 2001 From: Mateusz Gozdek Date: Wed, 10 Jun 2020 10:11:55 +0200 Subject: [PATCH 4/5] cli/cmd: getKubeconfig: refactor into smaller functions So resulting code is much easier to understand. Signed-off-by: Mateusz Gozdek --- cli/cmd/utils.go | 43 +++++++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/cli/cmd/utils.go b/cli/cmd/utils.go index d92994fbd..f0fec19bb 100644 --- a/cli/cmd/utils.go +++ b/cli/cmd/utils.go @@ -114,28 +114,47 @@ func expandKubeconfigPath(path string) string { // - KUBECONFIG environment variable. // - ~/.kube/config path, which is the default for kubectl. func getKubeconfig() (string, error) { - kubeconfig := viper.GetString(kubeconfigFlag) - if kubeconfig != "" { - return expandKubeconfigPath(kubeconfig), nil - } - - assetDir, err := getAssetDir() + assetKubeconfig, err := assetsKubeconfigPath() if err != nil { - return "", err + return "", fmt.Errorf("reading kubeconfig path from configuration failed: %w", err) } paths := []string{ - assetDir, + viper.GetString(kubeconfigFlag), + assetKubeconfig, os.Getenv(kubeconfigEnvVariable), + defaultKubeconfigPath, } - for _, path := range paths { - if path != "" { - return expandKubeconfigPath(path), nil + return expandKubeconfigPath(pickString(paths...)), nil +} + +// pickString returns first non-empty string. +func pickString(options ...string) string { + for _, option := range options { + if option != "" { + return option } } - return expandKubeconfigPath(defaultKubeconfigPath), nil + return "" +} + +// assetsKubeconfigPath reads the lokocfg configuration and returns +// the kubeconfig path defined in it. +// +// If no configuration is defined, empty string is returned. +func assetsKubeconfigPath() (string, error) { + assetDir, err := getAssetDir() + if err != nil { + return "", err + } + + if assetDir != "" { + return assetsKubeconfig(assetDir), nil + } + + return "", nil } func assetsKubeconfig(assetDir string) string { From 7470a24b2071caf7a973a58dd01c1ff82f285601 Mon Sep 17 00:00:00 2001 From: Mateusz Gozdek Date: Wed, 10 Jun 2020 10:12:21 +0200 Subject: [PATCH 5/5] cli/cmd: add tests for getKubeconfig To make sure we do it right, as otherwise it might be destructive. Signed-off-by: Mateusz Gozdek --- cli/cmd/utils_internal_test.go | 204 +++++++++++++++++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 cli/cmd/utils_internal_test.go diff --git a/cli/cmd/utils_internal_test.go b/cli/cmd/utils_internal_test.go new file mode 100644 index 000000000..9982e7caa --- /dev/null +++ b/cli/cmd/utils_internal_test.go @@ -0,0 +1,204 @@ +// Copyright 2020 The Lokomotive Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "io/ioutil" + "os" + "path/filepath" + "testing" + + "github.com/spf13/viper" +) + +type kubeconfigSources struct { + flag string + env string + configFile string +} + +func prepareKubeconfigSource(t *testing.T, k *kubeconfigSources) { + // Ensure viper flag is NOT empty. + viper.Set(kubeconfigFlag, k.flag) + + if k.env == "" { + // Ensure KUBECONFIG is not set. + if err := os.Unsetenv(kubeconfigEnvVariable); err != nil { + t.Fatalf("unsetting %q environment variable: %v", kubeconfigEnvVariable, err) + } + } + + if k.env != "" { + // Ensure KUBECONFIG IS set. + if err := os.Setenv(kubeconfigEnvVariable, k.env); err != nil { + t.Fatalf("setting %q environment variable: %v", kubeconfigEnvVariable, err) + } + } + + // Ensure there is no lokocfg configuration in working directory. + tmpDir, err := ioutil.TempDir("", "lokoctl-tests-") + if err != nil { + t.Fatalf("creating tmp dir: %v", err) + } + + t.Cleanup(func() { + if err := os.RemoveAll(tmpDir); err != nil { + t.Logf("removing temp dir %q: %v", tmpDir, err) + } + }) + + if err := os.Chdir(tmpDir); err != nil { + t.Fatalf("changing working directory to %q: %v", tmpDir, err) + } + + if k.configFile != "" { + path := filepath.Join(tmpDir, "cluster.lokocfg") + if err := ioutil.WriteFile(path, []byte(k.configFile), 0600); err != nil { + t.Fatalf("writing file %q: %v", path, err) + } + } +} + +func TestGetKubeconfigFlag(t *testing.T) { + expectedPath := "/foo" + + k := &kubeconfigSources{ + configFile: `cluster "packet" { + asset_dir = "/bad" + + cluster_name = "" + controller_count = 0 + facility = "" + management_cidrs = [] + node_private_cidr = "" + project_id = "" + ssh_pubkeys = [] + dns { + provider = "" + zone = "" + } + worker_pool "foo" { + count = 0 + } +}`, + flag: expectedPath, + env: "/badpath", + } + + prepareKubeconfigSource(t, k) + + kubeconfig, err := getKubeconfig() + if err != nil { + t.Fatalf("getting kubeconfig: %v", err) + } + + if kubeconfig != expectedPath { + t.Fatalf("expected %q, got %q", expectedPath, kubeconfig) + } +} + +func TestGetKubeconfigConfigFile(t *testing.T) { + expectedPath := assetsKubeconfig("/foo") + + k := &kubeconfigSources{ + configFile: `cluster "packet" { + asset_dir = "/foo" + + cluster_name = "" + controller_count = 0 + facility = "" + management_cidrs = [] + node_private_cidr = "" + project_id = "" + ssh_pubkeys = [] + dns { + provider = "" + zone = "" + } + worker_pool "foo" { + count = 0 + } +}`, + env: "/badpath", + } + + prepareKubeconfigSource(t, k) + + kubeconfig, err := getKubeconfig() + if err != nil { + t.Fatalf("getting kubeconfig: %v", err) + } + + if kubeconfig != expectedPath { + t.Fatalf("expected %q, got %q", expectedPath, kubeconfig) + } +} + +func TestGetKubeconfigBadConfigFile(t *testing.T) { + expectedPath := "" + + k := &kubeconfigSources{ + configFile: `cluster "packet" { + asset_dir = "/foo" +}`, + } + + prepareKubeconfigSource(t, k) + + kubeconfig, err := getKubeconfig() + if err == nil { + t.Errorf("getting kubeconfig with bad configuration should fail") + } + + if kubeconfig != expectedPath { + t.Fatalf("if getting kubeconfig fails, empty path should be returned") + } +} + +func TestGetKubeconfigEnvVariable(t *testing.T) { + expectedPath := "/foo" + + k := &kubeconfigSources{ + env: expectedPath, + } + + prepareKubeconfigSource(t, k) + + kubeconfig, err := getKubeconfig() + if err != nil { + t.Fatalf("getting kubeconfig: %v", err) + } + + if kubeconfig != expectedPath { + t.Fatalf("expected %q, got %q", expectedPath, kubeconfig) + } +} + +func TestGetKubeconfigDefault(t *testing.T) { + expectedPath := expandKubeconfigPath(defaultKubeconfigPath) + + k := &kubeconfigSources{} + + prepareKubeconfigSource(t, k) + + kubeconfig, err := getKubeconfig() + if err != nil { + t.Fatalf("getting kubeconfig: %v", err) + } + + if kubeconfig != expectedPath { + t.Fatalf("expected %q, got %q", expectedPath, kubeconfig) + } +}