From 5a16a65c5adf2414ba9f9f180d4ee66d0cfce44e Mon Sep 17 00:00:00 2001 From: John Houston Date: Fri, 13 Nov 2020 16:34:17 -0500 Subject: [PATCH] Change config_path -> config_paths --- kubernetes/provider.go | 35 ++++++++++++++++++++-------- kubernetes/provider_test.go | 39 +++++++++----------------------- website/docs/index.html.markdown | 16 ++++--------- 3 files changed, 40 insertions(+), 50 deletions(-) diff --git a/kubernetes/provider.go b/kubernetes/provider.go index a20c172cab..3245dbd647 100644 --- a/kubernetes/provider.go +++ b/kubernetes/provider.go @@ -6,6 +6,8 @@ import ( "fmt" "log" "net/http" + "os" + "strings" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" @@ -68,11 +70,11 @@ func Provider() *schema.Provider { DefaultFunc: schema.EnvDefaultFunc("KUBE_CLUSTER_CA_CERT_DATA", ""), Description: "PEM-encoded root certificates bundle for TLS authentication.", }, - "config_path": { - Type: schema.TypeString, + "config_paths": { + Type: schema.TypeList, + Elem: &schema.Schema{Type: schema.TypeString}, Optional: true, - DefaultFunc: schema.EnvDefaultFunc("KUBE_CONFIG_PATH", ""), - Description: "Path to the kube config file. Can be set with KUBE_CONFIG_PATH environment variable.", + Description: "A list of paths to kube config files. Can be set with KUBE_CONFIG_PATHS environment variable.", }, "config_context": { Type: schema.TypeString, @@ -260,13 +262,26 @@ func initializeConfiguration(d *schema.ResourceData) (*restclient.Config, error) overrides := &clientcmd.ConfigOverrides{} loader := &clientcmd.ClientConfigLoadingRules{} - if configPath, ok := d.GetOk("config_path"); ok && configPath.(string) != "" { - path, err := homedir.Expand(configPath.(string)) - if err != nil { - return nil, err + configPaths := []string{} + if v, ok := d.Get("config_paths").([]string); ok && len(v) > 0 { + configPaths = v + } else if v := os.Getenv("KUBE_CONFIG_PATHS"); v != "" { + // NOTE we have to do this here because the schema + // does not yet allow you to set a default for a TypeList + configPaths = strings.Split(v, ":") + } + + if len(configPaths) > 0 { + expandedPaths := []string{} + for _, p := range configPaths { + path, err := homedir.Expand(p) + if err != nil { + return nil, err + } + log.Printf("[DEBUG] Using kubeconfig: %s", path) + expandedPaths = append(expandedPaths, path) } - log.Printf("[DEBUG] Configuration file is: %s", path) - loader.ExplicitPath = path + loader.Precedence = expandedPaths ctxSuffix := "; default context" diff --git a/kubernetes/provider_test.go b/kubernetes/provider_test.go index d07876c0fe..3015b250e2 100644 --- a/kubernetes/provider_test.go +++ b/kubernetes/provider_test.go @@ -4,11 +4,12 @@ import ( "context" "errors" "fmt" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "os" "strings" "testing" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + gversion "github.com/hashicorp/go-version" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" @@ -72,7 +73,7 @@ func TestProvider_configure(t *testing.T) { resetEnv := unsetEnv(t) defer resetEnv() - os.Setenv("KUBECONFIG", "test-fixtures/kube-config.yaml") + os.Setenv("KUBE_CONFIG_PATHS", "test-fixtures/kube-config.yaml") os.Setenv("KUBE_CTX", "gcp") rc := terraform.NewResourceConfigRaw(map[string]interface{}{}) @@ -86,11 +87,8 @@ func TestProvider_configure(t *testing.T) { func unsetEnv(t *testing.T) func() { e := getEnv() - if err := os.Unsetenv("KUBECONFIG"); err != nil { - t.Fatalf("Error unsetting env var KUBECONFIG: %s", err) - } - if err := os.Unsetenv("KUBE_CONFIG"); err != nil { - t.Fatalf("Error unsetting env var KUBE_CONFIG: %s", err) + if err := os.Unsetenv("KUBE_CONFIG_PATHS"); err != nil { + t.Fatalf("Error unsetting env var KUBE_CONFIG_PATHS: %s", err) } if err := os.Unsetenv("KUBE_CTX"); err != nil { t.Fatalf("Error unsetting env var KUBE_CTX: %s", err) @@ -122,19 +120,13 @@ func unsetEnv(t *testing.T) func() { if err := os.Unsetenv("KUBE_INSECURE"); err != nil { t.Fatalf("Error unsetting env var KUBE_INSECURE: %s", err) } - if err := os.Unsetenv("KUBE_LOAD_CONFIG_FILE"); err != nil { - t.Fatalf("Error unsetting env var KUBE_LOAD_CONFIG_FILE: %s", err) - } if err := os.Unsetenv("KUBE_TOKEN"); err != nil { t.Fatalf("Error unsetting env var KUBE_TOKEN: %s", err) } return func() { - if err := os.Setenv("KUBE_CONFIG", e.Config); err != nil { - t.Fatalf("Error resetting env var KUBE_CONFIG: %s", err) - } - if err := os.Setenv("KUBECONFIG", e.Config); err != nil { - t.Fatalf("Error resetting env var KUBECONFIG: %s", err) + if err := os.Setenv("KUBE_CONFIG_PATHS", strings.Join(e.ConfigPaths, ":")); err != nil { + t.Fatalf("Error resetting env var KUBE_CONFIG_PATHS: %s", err) } if err := os.Setenv("KUBE_CTX", e.Ctx); err != nil { t.Fatalf("Error resetting env var KUBE_CTX: %s", err) @@ -166,9 +158,6 @@ func unsetEnv(t *testing.T) func() { if err := os.Setenv("KUBE_INSECURE", e.Insecure); err != nil { t.Fatalf("Error resetting env var KUBE_INSECURE: %s", err) } - if err := os.Setenv("KUBE_LOAD_CONFIG_FILE", e.LoadConfigFile); err != nil { - t.Fatalf("Error resetting env var KUBE_LOAD_CONFIG_FILE: %s", err) - } if err := os.Setenv("KUBE_TOKEN", e.Token); err != nil { t.Fatalf("Error resetting env var KUBE_TOKEN: %s", err) } @@ -187,14 +176,10 @@ func getEnv() *currentEnv { ClientKeyData: os.Getenv("KUBE_CLIENT_KEY_DATA"), ClusterCACertData: os.Getenv("KUBE_CLUSTER_CA_CERT_DATA"), Insecure: os.Getenv("KUBE_INSECURE"), - LoadConfigFile: os.Getenv("KUBE_LOAD_CONFIG_FILE"), Token: os.Getenv("KUBE_TOKEN"), } - if cfg := os.Getenv("KUBE_CONFIG"); cfg != "" { - e.Config = cfg - } - if cfg := os.Getenv("KUBECONFIG"); cfg != "" { - e.Config = cfg + if v := os.Getenv("KUBE_CONFIG_PATHS"); v != "" { + e.ConfigPaths = strings.Split(v, ":") } return e } @@ -203,8 +188,7 @@ func testAccPreCheck(t *testing.T) { ctx := context.TODO() hasFileCfg := (os.Getenv("KUBE_CTX_AUTH_INFO") != "" && os.Getenv("KUBE_CTX_CLUSTER") != "") || os.Getenv("KUBE_CTX") != "" || - os.Getenv("KUBECONFIG") != "" || - os.Getenv("KUBE_CONFIG") != "" + os.Getenv("KUBE_CONFIG_PATHS") != "" hasUserCredentials := os.Getenv("KUBE_USER") != "" && os.Getenv("KUBE_PASSWORD") != "" hasClientCert := os.Getenv("KUBE_CLIENT_CERT_DATA") != "" && os.Getenv("KUBE_CLIENT_KEY_DATA") != "" hasStaticCfg := (os.Getenv("KUBE_HOST") != "" && @@ -440,7 +424,7 @@ func clusterVersionLessThan(vs string) bool { } type currentEnv struct { - Config string + ConfigPaths []string Ctx string CtxAuthInfo string CtxCluster string @@ -451,7 +435,6 @@ type currentEnv struct { ClientKeyData string ClusterCACertData string Insecure string - LoadConfigFile string Token string } diff --git a/website/docs/index.html.markdown b/website/docs/index.html.markdown index b437a63c6d..e9687eead0 100644 --- a/website/docs/index.html.markdown +++ b/website/docs/index.html.markdown @@ -15,7 +15,9 @@ Use the navigation to the left to read about the available resources. ```hcl provider "kubernetes" { - config_path = "~/.kube/config" + config_paths = [ + "~/.kube/config" + ] config_context = "my-context" } @@ -79,12 +81,6 @@ the provider will try to use the service account token from the `/var/run/secret Detection of in-cluster execution is based on the sole availability both of the `KUBERNETES_SERVICE_HOST` and `KUBERNETES_SERVICE_PORT` environment variables, with non empty values. -```hcl -provider "kubernetes" { - load_config_file = "false" -} -``` - If you have any other static configuration setting specified in a config file or static configuration, in-cluster service account token will not be tried. ### Statically defined credentials @@ -93,8 +89,6 @@ Another way is **statically** define TLS certificate credentials: ```hcl provider "kubernetes" { - load_config_file = "false" - host = "https://104.196.242.174" client_certificate = "${file("~/.kube/client-cert.pem")}" @@ -107,8 +101,6 @@ or username and password (HTTP Basic Authorization): ```hcl provider "kubernetes" { - load_config_file = "false" - host = "https://104.196.242.174" username = "username" @@ -132,7 +124,7 @@ The following arguments are supported: * `client_certificate` - (Optional) PEM-encoded client certificate for TLS authentication. Can be sourced from `KUBE_CLIENT_CERT_DATA`. * `client_key` - (Optional) PEM-encoded client certificate key for TLS authentication. Can be sourced from `KUBE_CLIENT_KEY_DATA`. * `cluster_ca_certificate` - (Optional) PEM-encoded root certificates bundle for TLS authentication. Can be sourced from `KUBE_CLUSTER_CA_CERT_DATA`. -* `config_path` - (Optional) Path to the kube config file. Can be sourced from `KUBE_CONFIG`. +* `config_paths` - (Optional) A list of paths to the kube config files. Can be sourced from `KUBE_CONFIG_PATHS`, which allows `:` to be used to delimit multiple paths. * `config_context` - (Optional) Context to choose from the config file. Can be sourced from `KUBE_CTX`. * `config_context_auth_info` - (Optional) Authentication info context of the kube config (name of the kubeconfig user, `--user` flag in `kubectl`). Can be sourced from `KUBE_CTX_AUTH_INFO`. * `config_context_cluster` - (Optional) Cluster context of the kube config (name of the kubeconfig cluster, `--cluster` flag in `kubectl`). Can be sourced from `KUBE_CTX_CLUSTER`.