From ebf75face0407914248c0193b62777d6ca07e459 Mon Sep 17 00:00:00 2001 From: Stef Forrester Date: Mon, 1 Feb 2021 11:12:23 -0800 Subject: [PATCH 1/7] Add ConflictsWith to provider config In order to create a more explicit configuration, and more predictable behavior, this PR adds ConflictsWith to specific provider authentication attributes, effectively disallowing the use of conflicting methods of authentication, such as config_path and token. The provider now generates an error to tell the user that these options are mutually exclusive. --- GNUmakefile | 19 +- kubernetes/provider.go | 238 ++++++++++++++------ kubernetes/provider_test.go | 426 ++++++++++++++++++++++++++++++++++++ 3 files changed, 609 insertions(+), 74 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 4f2e07573d..97b60f8e8c 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -10,6 +10,12 @@ TF_PROV_DOCS := $(PWD)/kubernetes/test-infra/tfproviderdocs EXT_PROV_DIR := $(PWD)/kubernetes/test-infra/external-providers EXT_PROV_BIN := /tmp/.terraform.d/localhost/test/kubernetes/9.9.9/$(OS_ARCH)/terraform-provider-kubernetes_9.9.9_$(OS_ARCH) +ifdef KUBE_CONFIG_PATHS +KUBECONFIG1 := $(shell echo $(KUBE_CONFIG_PATHS) | cut -d\: -f1) +else +KUBECONFIG1 := $(shell echo $(KUBECONFIG) | cut -d\: -f1) +endif + ifneq ($(PWD),$(PROVIDER_DIR)) $(error "Makefile must be run from the provider directory") endif @@ -57,11 +63,14 @@ test: fmtcheck xargs -t -n4 go test $(TESTARGS) -timeout=30s -parallel=4 testacc: fmtcheck vet - rm -rf $(EXT_PROV_DIR)/.terraform $(EXT_PROV_DIR)/.terraform.lock.hcl || true - mkdir $(EXT_PROV_DIR)/.terraform - mkdir -p /tmp/.terraform.d/localhost/test/kubernetes/9.9.9/$(OS_ARCH) || true - ls $(EXT_PROV_BIN) || go build -o $(EXT_PROV_BIN) - cd $(EXT_PROV_DIR) && TF_CLI_CONFIG_FILE=$(EXT_PROV_DIR)/.terraformrc TF_PLUGIN_CACHE_DIR=$(EXT_PROV_DIR)/.terraform terraform init -upgrade + @rm -rf kubernetes/testdata || true + @mkdir kubernetes/testdata + @cp $(KUBECONFIG1) kubernetes/testdata/kubeconfig || (echo "Please set KUBE_CONFIG_PATHS or KUBECONFIG environment variable"; exit 1) + @rm -rf $(EXT_PROV_DIR)/.terraform $(EXT_PROV_DIR)/.terraform.lock.hcl || true + @mkdir $(EXT_PROV_DIR)/.terraform + @mkdir -p /tmp/.terraform.d/localhost/test/kubernetes/9.9.9/$(OS_ARCH) || true + @ls $(EXT_PROV_BIN) || go build -o $(EXT_PROV_BIN) + @cd $(EXT_PROV_DIR) && TF_CLI_CONFIG_FILE=$(EXT_PROV_DIR)/.terraformrc TF_PLUGIN_CACHE_DIR=$(EXT_PROV_DIR)/.terraform terraform init -upgrade TF_CLI_CONFIG_FILE=$(EXT_PROV_DIR)/.terraformrc TF_PLUGIN_CACHE_DIR=$(EXT_PROV_DIR)/.terraform TF_ACC=1 go test $(TEST) -v $(TESTARGS) -timeout 120m test-compile: diff --git a/kubernetes/provider.go b/kubernetes/provider.go index e310631bf3..a2153cda76 100644 --- a/kubernetes/provider.go +++ b/kubernetes/provider.go @@ -4,21 +4,20 @@ import ( "bytes" "context" "fmt" - "log" - "net/http" - "os" - "path/filepath" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/logging" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/mitchellh/go-homedir" apimachineryschema "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/discovery" "k8s.io/client-go/kubernetes" _ "k8s.io/client-go/plugin/pkg/client/auth" restclient "k8s.io/client-go/rest" + "log" + "net/http" + "os" + "path/filepath" "k8s.io/client-go/tools/clientcmd" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" @@ -29,82 +28,117 @@ func Provider() *schema.Provider { p := &schema.Provider{ Schema: map[string]*schema.Schema{ "host": { - Type: schema.TypeString, - Optional: true, - DefaultFunc: schema.EnvDefaultFunc("KUBE_HOST", ""), - Description: "The hostname (in form of URI) of Kubernetes master.", + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("KUBE_HOST", nil), + Description: "The hostname (in form of URI) of Kubernetes master.", + ConflictsWith: []string{"config_path", "config_paths"}, + ValidateDiagFunc: validation.ToDiagFunc(validation.IsURLWithHTTPorHTTPS), + // TODO: enable this when AtLeastOneOf works with optional attributes. + // https://github.com/hashicorp/terraform-plugin-sdk/issues/705 + // AtLeastOneOf: []string{"token", "exec", "username", "password", "client_certificate", "client_key"}, }, "username": { - Type: schema.TypeString, - Optional: true, - DefaultFunc: schema.EnvDefaultFunc("KUBE_USER", ""), - Description: "The username to use for HTTP basic authentication when accessing the Kubernetes master endpoint.", + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("KUBE_USER", nil), + Description: "The username to use for HTTP basic authentication when accessing the Kubernetes master endpoint.", + ConflictsWith: []string{"config_path", "config_paths", "exec", "token", "client_certificate", "client_key"}, + RequiredWith: []string{"password", "host"}, }, "password": { - Type: schema.TypeString, - Optional: true, - DefaultFunc: schema.EnvDefaultFunc("KUBE_PASSWORD", ""), - Description: "The password to use for HTTP basic authentication when accessing the Kubernetes master endpoint.", + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("KUBE_PASSWORD", nil), + Description: "The password to use for HTTP basic authentication when accessing the Kubernetes master endpoint.", + ConflictsWith: []string{"config_path", "config_paths", "exec", "token", "client_certificate", "client_key"}, + RequiredWith: []string{"username", "host"}, }, "insecure": { - Type: schema.TypeBool, - Optional: true, - DefaultFunc: schema.EnvDefaultFunc("KUBE_INSECURE", false), - Description: "Whether server should be accessed without verifying the TLS certificate.", + Type: schema.TypeBool, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("KUBE_INSECURE", nil), + Description: "Whether server should be accessed without verifying the TLS certificate.", + ConflictsWith: []string{"cluster_ca_certificate", "client_key", "client_certificate", "exec"}, }, "client_certificate": { - Type: schema.TypeString, - Optional: true, - DefaultFunc: schema.EnvDefaultFunc("KUBE_CLIENT_CERT_DATA", ""), - Description: "PEM-encoded client certificate for TLS authentication.", + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("KUBE_CLIENT_CERT_DATA", nil), + Description: "PEM-encoded client certificate for TLS authentication.", + ConflictsWith: []string{"config_path", "config_paths", "username", "password", "insecure"}, + RequiredWith: []string{"client_key", "cluster_ca_certificate", "host"}, }, "client_key": { - Type: schema.TypeString, - Optional: true, - DefaultFunc: schema.EnvDefaultFunc("KUBE_CLIENT_KEY_DATA", ""), - Description: "PEM-encoded client certificate key for TLS authentication.", + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("KUBE_CLIENT_KEY_DATA", nil), + Description: "PEM-encoded client certificate key for TLS authentication.", + ConflictsWith: []string{"config_path", "config_paths", "username", "password", "exec", "insecure"}, + RequiredWith: []string{"client_certificate", "cluster_ca_certificate", "host"}, }, "cluster_ca_certificate": { - Type: schema.TypeString, - Optional: true, - DefaultFunc: schema.EnvDefaultFunc("KUBE_CLUSTER_CA_CERT_DATA", ""), - Description: "PEM-encoded root certificates bundle for TLS authentication.", + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("KUBE_CLUSTER_CA_CERT_DATA", nil), + Description: "PEM-encoded root certificates bundle for TLS authentication.", + ConflictsWith: []string{"config_path", "config_paths", "insecure"}, + RequiredWith: []string{"host"}, + // TODO: enable this when AtLeastOneOf works with optional attributes. + // https://github.com/hashicorp/terraform-plugin-sdk/issues/705 + // AtLeastOneOf: []string{"token", "exec", "client_certificate", "client_key"}, }, "config_paths": { Type: schema.TypeList, Elem: &schema.Schema{Type: schema.TypeString}, + DefaultFunc: configPathsEnv, Optional: true, Description: "A list of paths to kube config files. Can be set with KUBE_CONFIG_PATHS environment variable.", + // config_paths conflicts with every attribute except for "insecure", since all of these options will be read from the kubeconfig. + ConflictsWith: []string{"config_path", "exec", "token", "host", "client_certificate", "client_key", "cluster_ca_certificate", "username", "password"}, }, "config_path": { - Type: schema.TypeString, - Optional: true, - DefaultFunc: schema.EnvDefaultFunc("KUBE_CONFIG_PATH", nil), - Description: "Path to the kube config file. Can be set with KUBE_CONFIG_PATH.", - ConflictsWith: []string{"config_paths"}, - }, - "config_context": { Type: schema.TypeString, Optional: true, - DefaultFunc: schema.EnvDefaultFunc("KUBE_CTX", ""), + DefaultFunc: schema.EnvDefaultFunc("KUBE_CONFIG_PATH", nil), + Description: "Path to the kube config file. Can be set with KUBE_CONFIG_PATH.", + // config_path conflicts with every attribute except for "insecure", since all of these options will be read from the kubeconfig. + ConflictsWith: []string{"config_paths", "exec", "token", "host", "client_certificate", "client_key", "cluster_ca_certificate", "username", "password"}, + }, + "config_context": { + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("KUBE_CTX", nil), + Description: "Context to choose from the kube config file. ", + ConflictsWith: []string{"exec", "token", "client_certificate", "client_key", "username", "password"}, + // TODO: enable this when AtLeastOneOf works with optional attributes. + // AtLeastOneOf: []string{"config_path", "config_paths"}, }, "config_context_auth_info": { - Type: schema.TypeString, - Optional: true, - DefaultFunc: schema.EnvDefaultFunc("KUBE_CTX_AUTH_INFO", ""), - Description: "", + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("KUBE_CTX_AUTH_INFO", nil), + Description: "Authentication info context of the kube config (name of the kubeconfig user, --user flag in kubectl).", + ConflictsWith: []string{"exec", "token", "client_certificate", "client_key", "username", "password"}, + // TODO: enable this when AtLeastOneOf works with optional attributes. + // AtLeastOneOf: []string{"config_path", "config_paths"}, }, "config_context_cluster": { - Type: schema.TypeString, - Optional: true, - DefaultFunc: schema.EnvDefaultFunc("KUBE_CTX_CLUSTER", ""), - Description: "", + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("KUBE_CTX_CLUSTER", nil), + Description: "Cluster context of the kube config (name of the kubeconfig cluster, --cluster flag in kubectl).", + ConflictsWith: []string{"exec", "token", "client_certificate", "client_key", "username", "password"}, + // TODO: enable this when AtLeastOneOf works with optional attributes. + // AtLeastOneOf: []string{"config_path", "config_paths"}, }, "token": { - Type: schema.TypeString, - Optional: true, - DefaultFunc: schema.EnvDefaultFunc("KUBE_TOKEN", ""), - Description: "Token to authenticate an service account", + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("KUBE_TOKEN", nil), + Description: "Bearer token for authenticating the Kubernetes API.", + ConflictsWith: []string{"config_path", "config_paths", "exec", "client_certificate", "client_key", "username", "password"}, + RequiredWith: []string{"host"}, }, "exec": { Type: schema.TypeList, @@ -132,7 +166,9 @@ func Provider() *schema.Provider { }, }, }, - Description: "", + Description: "Configuration block to use an exec-based credential plugin, e.g. call an external command to receive user credentials.", + ConflictsWith: []string{"config_path", "config_paths", "token", "client_certificate", "client_key", "username", "password", "insecure"}, + RequiredWith: []string{"host", "cluster_ca_certificate"}, }, }, @@ -194,6 +230,22 @@ func Provider() *schema.Provider { return p } +// configPathsEnv fetches the value of the environment variable KUBE_CONFIG_PATHS, if defined. +func configPathsEnv() (interface{}, error) { + value, exists := os.LookupEnv("KUBE_CONFIG_PATHS") + if exists { + log.Print("[DEBUG] using environment variable KUBE_CONFIG_PATHS to define config_paths") + log.Printf("[DEBUG] value of KUBE_CONFIG_PATHS: %v", value) + pathList := filepath.SplitList(value) + configPaths := new([]interface{}) + for _, p := range pathList { + *configPaths = append(*configPaths, p) + } + return *configPaths, nil + } + return nil, nil +} + type KubeClientsets interface { MainClientset() (*kubernetes.Clientset, error) AggregatorClientset() (*aggregator.Clientset, error) @@ -212,6 +264,10 @@ func (k kubeClientsets) MainClientset() (*kubernetes.Clientset, error) { return k.mainClientset, nil } + if err := checkConfigurationValid(k.configData); err != nil { + return nil, err + } + if k.config != nil { kc, err := kubernetes.NewForConfig(k.config) if err != nil { @@ -236,6 +292,52 @@ func (k kubeClientsets) AggregatorClientset() (*aggregator.Clientset, error) { return k.aggregatorClientset, nil } +var apiTokenMountPath = "/var/run/secrets/kubernetes.io/serviceaccount" + +func inCluster() bool { + host, port := os.Getenv("KUBERNETES_SERVICE_HOST"), os.Getenv("KUBERNETES_SERVICE_PORT") + if host == "" || port == "" { + return false + } + + if _, err := os.Stat(apiTokenMountPath); err != nil { + return false + } + return true +} + +var authDocumentationURL = "https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs#authentication" + +func checkConfigurationValid(d *schema.ResourceData) error { + if inCluster() { + log.Printf("[DEBUG] Terraform appears to be running inside the Kubernetes cluster") + return nil + } + + if os.Getenv("KUBE_CONFIG_PATHS") != "" { + return nil + } + + atLeastOneOf := []string{ + "host", + "config_path", + "config_paths", + "client_certificate", + "token", + "exec", + } + for _, a := range atLeastOneOf { + if _, ok := d.GetOk(a); ok { + return nil + } + } + + return fmt.Errorf(`provider not configured: you must configure a path to your kubeconfig +or explicitly supply credentials via the provider block or environment variables. + +See our documentation at: %s`, authDocumentationURL) +} + func providerConfigure(ctx context.Context, d *schema.ResourceData, terraformVersion string) (interface{}, diag.Diagnostics) { // Config initialization cfg, err := initializeConfiguration(d) @@ -270,7 +372,9 @@ func providerConfigure(ctx context.Context, d *schema.ResourceData, terraformVer func initializeConfiguration(d *schema.ResourceData) (*restclient.Config, error) { overrides := &clientcmd.ConfigOverrides{} - loader := &clientcmd.ClientConfigLoadingRules{} + loader := &clientcmd.ClientConfigLoadingRules{ + WarnIfAllMissing: true, + } configPaths := []string{} @@ -280,10 +384,6 @@ func initializeConfiguration(d *schema.ResourceData) (*restclient.Config, error) for _, p := range v { configPaths = append(configPaths, p.(string)) } - } 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 = filepath.SplitList(v) } if len(configPaths) > 0 { @@ -310,7 +410,7 @@ func initializeConfiguration(d *schema.ResourceData) (*restclient.Config, error) authInfo, authInfoOk := d.GetOk("config_context_auth_info") cluster, clusterOk := d.GetOk("config_context_cluster") if ctxOk || authInfoOk || clusterOk { - ctxSuffix = "; overriden context" + ctxSuffix = "; overridden context" if ctxOk { overrides.CurrentContext = kubectx.(string) ctxSuffix += fmt.Sprintf("; config ctx: %s", overrides.CurrentContext) @@ -331,16 +431,16 @@ func initializeConfiguration(d *schema.ResourceData) (*restclient.Config, error) } // Overriding with static configuration - if v, ok := d.GetOk("insecure"); ok { + if v, ok := d.GetOk("insecure"); ok && v != "" { overrides.ClusterInfo.InsecureSkipTLSVerify = v.(bool) } - if v, ok := d.GetOk("cluster_ca_certificate"); ok { + if v, ok := d.GetOk("cluster_ca_certificate"); ok && v != "" { overrides.ClusterInfo.CertificateAuthorityData = bytes.NewBufferString(v.(string)).Bytes() } - if v, ok := d.GetOk("client_certificate"); ok { + if v, ok := d.GetOk("client_certificate"); ok && v != "" { overrides.AuthInfo.ClientCertificateData = bytes.NewBufferString(v.(string)).Bytes() } - if v, ok := d.GetOk("host"); ok { + if v, ok := d.GetOk("host"); ok && v != "" { // Server has to be the complete address of the kubernetes cluster (scheme://hostname:port), not just the hostname, // because `overrides` are processed too late to be taken into account by `defaultServerUrlFor()`. // This basically replicates what defaultServerUrlFor() does with config but for overrides, @@ -355,16 +455,16 @@ func initializeConfiguration(d *schema.ResourceData) (*restclient.Config, error) overrides.ClusterInfo.Server = host.String() } - if v, ok := d.GetOk("username"); ok { + if v, ok := d.GetOk("username"); ok && v != "" { overrides.AuthInfo.Username = v.(string) } - if v, ok := d.GetOk("password"); ok { + if v, ok := d.GetOk("password"); ok && v != "" { overrides.AuthInfo.Password = v.(string) } - if v, ok := d.GetOk("client_key"); ok { + if v, ok := d.GetOk("client_key"); ok && v != "" { overrides.AuthInfo.ClientKeyData = bytes.NewBufferString(v.(string)).Bytes() } - if v, ok := d.GetOk("token"); ok { + if v, ok := d.GetOk("token"); ok && v != "" { overrides.AuthInfo.Token = v.(string) } diff --git a/kubernetes/provider_test.go b/kubernetes/provider_test.go index 6135705c50..5448e5a1eb 100644 --- a/kubernetes/provider_test.go +++ b/kubernetes/provider_test.go @@ -6,6 +6,7 @@ import ( "fmt" "os" "path/filepath" + "regexp" "strings" "testing" @@ -166,6 +167,9 @@ func getEnv() *currentEnv { return e } +// testAccPreCheck verifies and sets required provider testing configuration +// This PreCheck function should be present in every acceptance test. It allows +// test configurations to omit a provider configuration func testAccPreCheck(t *testing.T) { ctx := context.TODO() hasFileCfg := (os.Getenv("KUBE_CTX_AUTH_INFO") != "" && os.Getenv("KUBE_CTX_CLUSTER") != "") || @@ -202,6 +206,37 @@ func testAccPreCheck(t *testing.T) { return } +// testAccPreCheckInternal configures the provider for internal tests. +// This is the equivalent of running `terraform init`, but with a bare +// minimum configuration, to create a fully separate environment where +// all configuration options (including environment variables) can be +// tested separately from the user's environment. It is used exclusively +// in functions labelled testAccKubernetesProvider_*. +func testAccPreCheckInternal(t *testing.T) { + ctx := context.TODO() + unsetEnv(t) + diags := testAccProvider.Configure(ctx, terraform.NewResourceConfigRaw(nil)) + if diags.HasError() { + t.Fatal(diags[0].Summary) + } + return +} + +// testAccPreCheckInternal_setEnv is used for internal testing where +// specific environment variables are needed to configure the provider. +func testAccPreCheckInternal_setEnv(t *testing.T, envVars map[string]string) { + ctx := context.TODO() + unsetEnv(t) + for k, v := range envVars { + os.Setenv(k, v) + } + diags := testAccProvider.Configure(ctx, terraform.NewResourceConfigRaw(nil)) + if diags.HasError() { + t.Fatal(diags[0].Summary) + } + return +} + func getClusterVersion() (*gversion.Version, error) { meta := testAccProvider.Meta() @@ -436,3 +471,394 @@ func requiredProviders() string { } `) } + +// testAccProviderFactoriesInternal is a factory used for provider configuration testing. +// This should only be used for TestAccKubernetesProvider_ tests which need to +// reference the provider instance itself. Other testing should use testAccProviderFactories. +var testAccProviderFactoriesInternal = map[string]func() (*schema.Provider, error){ + "kubernetes": func() (*schema.Provider, error) { + return Provider(), nil + }, +} + +func TestAccKubernetesProviderConfig_config_path(t *testing.T) { + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheckInternal(t) }, + ProviderFactories: testAccProviderFactoriesInternal, + Steps: []resource.TestStep{ + { + Config: testAccKubernetesProviderConfig( + providerConfig_config_path("./testdata/kubeconfig"), + ), + PlanOnly: true, + ExpectNonEmptyPlan: true, + }, + { + Config: testAccKubernetesProviderConfig( + providerConfig_config_path("./testdata/kubeconfig") + + providerConfig_config_context("test-context"), + ), + PlanOnly: true, + ExpectNonEmptyPlan: true, + }, + { + Config: testAccKubernetesProviderConfig( + providerConfig_config_path("./missing/file"), + ), + ExpectError: regexp.MustCompile("could not open kubeconfig"), + PlanOnly: true, + ExpectNonEmptyPlan: true, + }, + { + Config: testAccKubernetesProviderConfig( + providerConfig_config_path("./testdata/kubeconfig") + + providerConfig_token("test-token"), + ), + ExpectError: regexp.MustCompile(`"config_path": conflicts with token`), + PlanOnly: true, + ExpectNonEmptyPlan: true, + }, + { + Config: testAccKubernetesProviderConfig( + providerConfig_config_path("./testdata/kubeconfig") + + providerConfig_host("test-host"), + ), + ExpectError: regexp.MustCompile(`"config_path": conflicts with host`), + PlanOnly: true, + ExpectNonEmptyPlan: true, + }, + { + Config: testAccKubernetesProviderConfig( + providerConfig_config_path("./testdata/kubeconfig") + + providerConfig_cluster_ca_certificate("test-ca-cert"), + ), + ExpectError: regexp.MustCompile(`"config_path": conflicts with cluster_ca_certificate`), + PlanOnly: true, + ExpectNonEmptyPlan: true, + }, + { + Config: testAccKubernetesProviderConfig( + providerConfig_config_path("./testdata/kubeconfig") + + providerConfig_client_cert("test-client-cert"), + ), + ExpectError: regexp.MustCompile(`"config_path": conflicts with client_certificate`), + PlanOnly: true, + ExpectNonEmptyPlan: true, + }, + { + Config: testAccKubernetesProviderConfig( + providerConfig_config_path("./testdata/kubeconfig") + + providerConfig_client_key("test-client-key"), + ), + ExpectError: regexp.MustCompile(`"config_path": conflicts with client_key`), + PlanOnly: true, + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func TestAccKubernetesProviderConfig_config_paths(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheckInternal(t) }, + ProviderFactories: testAccProviderFactoriesInternal, + Steps: []resource.TestStep{ + { + Config: testAccKubernetesProviderConfig( + providerConfig_config_paths(`["./testdata/kubeconfig", "./testdata/kubeconfig"]`), + ), + PlanOnly: true, + ExpectNonEmptyPlan: true, + }, + { + Config: testAccKubernetesProviderConfig( + providerConfig_config_paths(`["./testdata/kubeconfig"]`) + + providerConfig_config_context("test-context"), + ), + PlanOnly: true, + ExpectNonEmptyPlan: true, + }, + { + Config: testAccKubernetesProviderConfig( + providerConfig_config_paths(`["./missing/file", "./testdata/kubeconfig"]`), + ), + ExpectError: regexp.MustCompile("could not open kubeconfig"), + PlanOnly: true, + ExpectNonEmptyPlan: true, + }, + { + Config: testAccKubernetesProviderConfig( + providerConfig_config_path("./internal/testdata/kubeconfig") + + providerConfig_config_paths(`["./testdata/kubeconfig", "./testdata/kubeconfig"]`), + ), + ExpectError: regexp.MustCompile(`"config_path": conflicts with config_paths`), + PlanOnly: true, + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func TestAccKubernetesProviderConfig_config_paths_env(t *testing.T) { + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheckInternal_setEnv(t, map[string]string{ + "KUBE_CONFIG_PATHS": strings.Join([]string{ + "./testdata/kubeconfig", + "./testdata/kubeconfig", + }, string(os.PathListSeparator)), + }) + }, + ProviderFactories: testAccProviderFactoriesInternal, + Steps: []resource.TestStep{ + { + Config: testAccKubernetesProviderConfig("# empty"), + PlanOnly: true, + ExpectNonEmptyPlan: true, + }, + { + Config: testAccKubernetesProviderConfig("# empty"), + PlanOnly: true, + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func TestAccKubernetesProviderConfig_config_paths_env_wantError(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheckInternal_setEnv(t, map[string]string{ + "KUBE_CONFIG_PATHS": strings.Join([]string{ + "./testdata/kubeconfig", + "./testdata/kubeconfig", + }, string(os.PathListSeparator)), + "KUBE_CONFIG_PATH": "./testdata/kubeconfig", + }) + }, + ProviderFactories: testAccProviderFactoriesInternal, + Steps: []resource.TestStep{ + { + Config: testAccKubernetesProviderConfig("# empty"), + ExpectError: regexp.MustCompile(`"config_path": conflicts with config_paths`), + PlanOnly: true, + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func TestAccKubernetesProviderConfig_host_env_wantError(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheckInternal_setEnv(t, map[string]string{ + "KUBE_HOST": "test-host", + "KUBE_CONFIG_PATHS": strings.Join([]string{ + "./testdata/kubeconfig", + "./testdata/kubeconfig", + }, string(os.PathListSeparator)), + }) + }, + ProviderFactories: testAccProviderFactoriesInternal, + Steps: []resource.TestStep{ + { + Config: testAccKubernetesProviderConfig("# empty"), + ExpectError: regexp.MustCompile(`"host": conflicts with config_paths`), + PlanOnly: true, + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func TestAccKubernetesProviderConfig_host(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheckInternal(t) }, + ProviderFactories: testAccProviderFactoriesInternal, + Steps: []resource.TestStep{ + { + Config: testAccKubernetesProviderConfig( + providerConfig_host("https://test-host") + + providerConfig_token("test-token"), + ), + PlanOnly: true, + ExpectNonEmptyPlan: true, + }, + { + Config: testAccKubernetesProviderConfig( + providerConfig_host("http://test-host") + + providerConfig_token("test-token"), + ), + PlanOnly: true, + ExpectNonEmptyPlan: true, + }, + { + Config: testAccKubernetesProviderConfig( + providerConfig_host("https://127.0.0.1") + + providerConfig_token("test-token"), + ), + PlanOnly: true, + ExpectNonEmptyPlan: true, + }, + { + Config: testAccKubernetesProviderConfig( + providerConfig_host("test-host") + + providerConfig_token("test-token"), + ), + PlanOnly: true, + ExpectNonEmptyPlan: true, + ExpectError: regexp.MustCompile(`Error: expected "host" to have a host, got test-host`), + }, + { + Config: testAccKubernetesProviderConfig( + providerConfig_exec("test-exec"), + ), + PlanOnly: true, + ExpectNonEmptyPlan: true, + // Error: "exec": all of `host,exec` must be specified + ExpectError: regexp.MustCompile("exec,host"), + }, + { + Config: testAccKubernetesProviderConfig( + providerConfig_exec("test-exec") + + providerConfig_cluster_ca_certificate("test-ca-cert"), + ), + PlanOnly: true, + ExpectNonEmptyPlan: true, + // Error: "exec": all of `cluster_ca_certificate,exec,host` must be specified + ExpectError: regexp.MustCompile("cluster_ca_certificate,exec,host"), + }, + { + Config: testAccKubernetesProviderConfig( + providerConfig_exec("test-exec") + + providerConfig_host("https://test-host") + + providerConfig_cluster_ca_certificate("test-ca-cert"), + ), + PlanOnly: true, + ExpectNonEmptyPlan: true, + }, + { + Config: testAccKubernetesProviderConfig( + providerConfig_token("test-token"), + ), + PlanOnly: true, + ExpectNonEmptyPlan: true, + // Error: "host": all of `host,token` must be specified + ExpectError: regexp.MustCompile("host,token"), + }, + { + Config: testAccKubernetesProviderConfig( + providerConfig_cluster_ca_certificate("test-cert"), + ), + PlanOnly: true, + ExpectNonEmptyPlan: true, + // Error: "cluster_ca_certificate": all of `cluster_ca_certificate,host` must be specified + ExpectError: regexp.MustCompile("cluster_ca_certificate,host"), + }, + { + Config: testAccKubernetesProviderConfig( + providerConfig_host("https://test-host") + + providerConfig_cluster_ca_certificate("test-cert"), + ), + PlanOnly: true, + ExpectNonEmptyPlan: true, + }, + { + Config: testAccKubernetesProviderConfig( + providerConfig_host("https://test-host") + + providerConfig_cluster_ca_certificate("test-cert") + + providerConfig_token("test-token"), + ), + PlanOnly: true, + ExpectNonEmptyPlan: true, + }, + { + Config: testAccKubernetesProviderConfig( + providerConfig_host("https://test-host") + + providerConfig_cluster_ca_certificate("test-ca-cert") + + providerConfig_client_cert("test-client-cert"), + ), + PlanOnly: true, + ExpectNonEmptyPlan: true, + // Error: "client_certificate": all of `client_certificate,client_key,cluster_ca_certificate,host` must be specified + ExpectError: regexp.MustCompile("client_certificate,client_key,cluster_ca_certificate,host"), + }, + }, + }) +} + +// testAccKubernetesProviderConfig is used together with the providerConfig_* functions +// to assemble a Kubernetes provider configuration with interchangeable options. +func testAccKubernetesProviderConfig(providerConfig string) string { + return fmt.Sprintf(`provider "kubernetes" { + %s +} + +# Needed for provider initialization. +resource kubernetes_namespace "test" { + metadata { + name = "tf-k8s-acc-test" + } +} +`, providerConfig) +} + +func providerConfig_config_path(path string) string { + return fmt.Sprintf(` + config_path = "%s" +`, path) +} + +func providerConfig_config_context(context string) string { + return fmt.Sprintf(` + config_context = "%s" +`, context) +} + +func providerConfig_config_paths(paths string) string { + return fmt.Sprintf(` + config_paths = %s +`, paths) +} + +func providerConfig_token(token string) string { + return fmt.Sprintf(` + token = "%s" +`, token) +} + +func providerConfig_cluster_ca_certificate(ca_cert string) string { + return fmt.Sprintf(` + cluster_ca_certificate = "%s" +`, ca_cert) +} + +func providerConfig_client_cert(client_cert string) string { + return fmt.Sprintf(` + client_certificate = "%s" +`, client_cert) +} + +func providerConfig_client_key(client_key string) string { + return fmt.Sprintf(` + client_key = "%s" +`, client_key) +} + +func providerConfig_host(host string) string { + return fmt.Sprintf(` + host = "%s" +`, host) +} + +func providerConfig_exec(clusterName string) string { + return fmt.Sprintf(` + exec { + api_version = "client.authentication.k8s.io/v1alpha1" + args = ["eks", "get-token", "--cluster-name", "%s"] + command = "aws" + } +`, clusterName) +} From ff0db5893d6318ff511e7362b1fea4a1dce5c3ff Mon Sep 17 00:00:00 2001 From: Stef Forrester Date: Fri, 19 Feb 2021 15:43:16 -0800 Subject: [PATCH 2/7] Update examples used for testing ConflictsWith --- kubernetes/test-infra/eks/.terraform.lock.hcl | 147 ++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 kubernetes/test-infra/eks/.terraform.lock.hcl diff --git a/kubernetes/test-infra/eks/.terraform.lock.hcl b/kubernetes/test-infra/eks/.terraform.lock.hcl new file mode 100644 index 0000000000..a9b02f8227 --- /dev/null +++ b/kubernetes/test-infra/eks/.terraform.lock.hcl @@ -0,0 +1,147 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "localhost/test/helm" { + version = "9.9.9" + constraints = "9.9.9" + hashes = [ + "h1:npZpS0MeIa75Fqq2LaEKcYZ8oi6rOogciOYH+oaCtvY=", + ] +} + +provider "localhost/test/kubernetes" { + version = "9.9.9" + constraints = "9.9.9" + hashes = [ + "h1:SWuBXYSfT0iDYpGWgBf/EhnzjCqlsuMQyFRl/co1Uyg=", + ] +} + +provider "registry.terraform.io/hashicorp/aws" { + version = "3.22.0" + constraints = ">= 3.22.0, 3.22.0" + hashes = [ + "h1:8aWXjFcmEi64P0TMHOCQXWws+/SmvJQrNvHlzdktKOM=", + "zh:4a9a66caf1964cdd3b61fb3ebb0da417195a5529cb8e496f266b0778335d11c8", + "zh:514f2f006ae68db715d86781673faf9483292deab235c7402ff306e0e92ea11a", + "zh:5277b61109fddb9011728f6650ef01a639a0590aeffe34ed7de7ba10d0c31803", + "zh:67784dc8c8375ab37103eea1258c3334ee92be6de033c2b37e3a2a65d0005142", + "zh:76d4c8be2ca4a3294fb51fb58de1fe03361d3bc403820270cc8e71a04c5fa806", + "zh:8f90b1cfdcf6e8fb1a9d0382ecaa5056a3a84c94e313fbf9e92c89de271cdede", + "zh:d0ac346519d0df124df89be2d803eb53f373434890f6ee3fb37112802f9eac59", + "zh:d6256feedada82cbfb3b1dd6dd9ad02048f23120ab50e6146a541cb11a108cc1", + "zh:db2fe0d2e77c02e9a74e1ed694aa352295a50283f9a1cf896e5be252af14e9f4", + "zh:eda61e889b579bd90046939a5b40cf5dc9031fb5a819fc3e4667a78bd432bdb2", + ] +} + +provider "registry.terraform.io/hashicorp/helm" { + version = "2.0.3" + hashes = [ + "h1:eUr4dHyxlcLmLja0wBgJC7t5bfHzbtACyuumKPuDrGs=", + "zh:154e0aa489e474e2eeb3de94be7666133faf6fd950712a640425b2bf3a81ee95", + "zh:16a2be6c4b61d0c5205c63816148c7ab0c8f56a75c05e8d897fa4d5cac0c029a", + "zh:189e47bc723f8c29bcfe2c1638d43b8148f614ea86e642f4b50b2acb4b760224", + "zh:3763901d3630213002cb8c70bb24c628cd29738ff6591585250ea8636264abd6", + "zh:4822f85e4700ea049384523d98de0ef7d83549844b13e94bbd544cec05557a9a", + "zh:62c5b87b09e0051bab0b712e3ad465fd53e66f9619dbe76ee23519d1087d8a05", + "zh:a0a6a842b11190dd1841e98bbb74961074e7ffb95984be5cc392df9f532d803e", + "zh:beac4e6806e77447e1018f3404a5fbf782d20d82a0d9b4a31e9bfc7d2bbecab6", + "zh:e1bbaa09bf4f4a91ec7606f84d2e0200a02e7b24d045e8b5daebd87d7a75b7ce", + "zh:ed1e05c50212d4f57435ccdd68cfb98d8395927c316df76d1dd6509566d3aeaa", + "zh:fdc687e16a964bb652ddb670f6832fdead25235eca551796cfed70ec07d94931", + ] +} + +provider "registry.terraform.io/hashicorp/kubernetes" { + version = "2.0.2" + constraints = ">= 1.11.1" + hashes = [ + "h1:PRfDnUFBD4ud7SgsMAa5S2Gd60FeriD1PWE6EifjXB0=", + "zh:4e66d509c828b0a2e599a567ad470bf85ebada62788aead87a8fb621301dec55", + "zh:55ca6466a82f60d2c9798d171edafacc9ea4991aa7aa32ed5d82d6831cf44542", + "zh:65741e6910c8b1322d9aef5dda4d98d1e6409aebc5514b518f46019cd06e1b47", + "zh:79456ca037c19983977285703f19f4b04f7eadcf8eb6af21f5ea615026271578", + "zh:7c39ced4dc44181296721715005e390021770077012c206ab4c209fb704b34d0", + "zh:86856c82a6444c19b3e3005e91408ac68eb010c9218c4c4119fc59300b107026", + "zh:999865090c72fa9b85c45e76b20839da51714ae429d1ab14b7d8ce66c2655abf", + "zh:a3ea0ae37c61b4bfe81f7a395fb7b5ba61564e7d716d7a191372c3c983271d13", + "zh:d9061861822933ebb2765fa691aeed2930ee495bfb6f72a5bdd88f43ccd9e038", + "zh:e04adbe0d5597d1fdd4f418be19c9df171f1d709009f63b8ce1239b71b4fa45a", + ] +} + +provider "registry.terraform.io/hashicorp/local" { + version = "2.1.0" + constraints = ">= 1.4.0" + hashes = [ + "h1:EYZdckuGU3n6APs97nS2LxZm3dDtGqyM4qaIvsmac8o=", + "zh:0f1ec65101fa35050978d483d6e8916664b7556800348456ff3d09454ac1eae2", + "zh:36e42ac19f5d68467aacf07e6adcf83c7486f2e5b5f4339e9671f68525fc87ab", + "zh:6db9db2a1819e77b1642ec3b5e95042b202aee8151a0256d289f2e141bf3ceb3", + "zh:719dfd97bb9ddce99f7d741260b8ece2682b363735c764cac83303f02386075a", + "zh:7598bb86e0378fd97eaa04638c1a4c75f960f62f69d3662e6d80ffa5a89847fe", + "zh:ad0a188b52517fec9eca393f1e2c9daea362b33ae2eb38a857b6b09949a727c1", + "zh:c46846c8df66a13fee6eff7dc5d528a7f868ae0dcf92d79deaac73cc297ed20c", + "zh:dc1a20a2eec12095d04bf6da5321f535351a594a636912361db20eb2a707ccc4", + "zh:e57ab4771a9d999401f6badd8b018558357d3cbdf3d33cc0c4f83e818ca8e94b", + "zh:ebdcde208072b4b0f8d305ebf2bfdc62c926e0717599dcf8ec2fd8c5845031c3", + "zh:ef34c52b68933bedd0868a13ccfd59ff1c820f299760b3c02e008dc95e2ece91", + ] +} + +provider "registry.terraform.io/hashicorp/null" { + version = "3.1.0" + constraints = ">= 2.1.0" + hashes = [ + "h1:vpC6bgUQoJ0znqIKVFevOdq+YQw42bRq0u+H3nto8nA=", + "zh:02a1675fd8de126a00460942aaae242e65ca3380b5bb192e8773ef3da9073fd2", + "zh:53e30545ff8926a8e30ad30648991ca8b93b6fa496272cd23b26763c8ee84515", + "zh:5f9200bf708913621d0f6514179d89700e9aa3097c77dac730e8ba6e5901d521", + "zh:9ebf4d9704faba06b3ec7242c773c0fbfe12d62db7d00356d4f55385fc69bfb2", + "zh:a6576c81adc70326e4e1c999c04ad9ca37113a6e925aefab4765e5a5198efa7e", + "zh:a8a42d13346347aff6c63a37cda9b2c6aa5cc384a55b2fe6d6adfa390e609c53", + "zh:c797744d08a5307d50210e0454f91ca4d1c7621c68740441cf4579390452321d", + "zh:cecb6a304046df34c11229f20a80b24b1603960b794d68361a67c5efe58e62b8", + "zh:e1371aa1e502000d9974cfaff5be4cfa02f47b17400005a16f14d2ef30dc2a70", + "zh:fc39cc1fe71234a0b0369d5c5c7f876c71b956d23d7d6f518289737a001ba69b", + "zh:fea4227271ebf7d9e2b61b89ce2328c7262acd9fd190e1fd6d15a591abfa848e", + ] +} + +provider "registry.terraform.io/hashicorp/random" { + version = "3.1.0" + constraints = ">= 2.1.0" + hashes = [ + "h1:BZMEPucF+pbu9gsPk0G0BHx7YP04+tKdq2MrRDF1EDM=", + "zh:2bbb3339f0643b5daa07480ef4397bd23a79963cc364cdfbb4e86354cb7725bc", + "zh:3cd456047805bf639fbf2c761b1848880ea703a054f76db51852008b11008626", + "zh:4f251b0eda5bb5e3dc26ea4400dba200018213654b69b4a5f96abee815b4f5ff", + "zh:7011332745ea061e517fe1319bd6c75054a314155cb2c1199a5b01fe1889a7e2", + "zh:738ed82858317ccc246691c8b85995bc125ac3b4143043219bd0437adc56c992", + "zh:7dbe52fac7bb21227acd7529b487511c91f4107db9cc4414f50d04ffc3cab427", + "zh:a3a9251fb15f93e4cfc1789800fc2d7414bbc18944ad4c5c98f466e6477c42bc", + "zh:a543ec1a3a8c20635cf374110bd2f87c07374cf2c50617eee2c669b3ceeeaa9f", + "zh:d9ab41d556a48bd7059f0810cf020500635bfc696c9fc3adab5ea8915c1d886b", + "zh:d9e13427a7d011dbd654e591b0337e6074eef8c3b9bb11b2e39eaaf257044fd7", + "zh:f7605bd1437752114baf601bdf6931debe6dc6bfe3006eb7e9bb9080931dca8a", + ] +} + +provider "registry.terraform.io/hashicorp/template" { + version = "2.2.0" + constraints = ">= 2.1.0" + hashes = [ + "h1:94qn780bi1qjrbC3uQtjJh3Wkfwd5+tTtJHOb7KTg9w=", + "zh:01702196f0a0492ec07917db7aaa595843d8f171dc195f4c988d2ffca2a06386", + "zh:09aae3da826ba3d7df69efeb25d146a1de0d03e951d35019a0f80e4f58c89b53", + "zh:09ba83c0625b6fe0a954da6fbd0c355ac0b7f07f86c91a2a97849140fea49603", + "zh:0e3a6c8e16f17f19010accd0844187d524580d9fdb0731f675ffcf4afba03d16", + "zh:45f2c594b6f2f34ea663704cc72048b212fe7d16fb4cfd959365fa997228a776", + "zh:77ea3e5a0446784d77114b5e851c970a3dde1e08fa6de38210b8385d7605d451", + "zh:8a154388f3708e3df5a69122a23bdfaf760a523788a5081976b3d5616f7d30ae", + "zh:992843002f2db5a11e626b3fc23dc0c87ad3729b3b3cff08e32ffb3df97edbde", + "zh:ad906f4cebd3ec5e43d5cd6dc8f4c5c9cc3b33d2243c89c5fc18f97f7277b51d", + "zh:c979425ddb256511137ecd093e23283234da0154b7fa8b21c2687182d9aea8b2", + ] +} From 7651347c08fb9944b35d3dd384c17ae8a01aa7e9 Mon Sep 17 00:00:00 2001 From: Stef Forrester Date: Fri, 19 Feb 2021 16:17:18 -0800 Subject: [PATCH 3/7] Fix function name --- kubernetes/provider_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kubernetes/provider_test.go b/kubernetes/provider_test.go index 5448e5a1eb..a0e819341f 100644 --- a/kubernetes/provider_test.go +++ b/kubernetes/provider_test.go @@ -211,7 +211,7 @@ func testAccPreCheck(t *testing.T) { // minimum configuration, to create a fully separate environment where // all configuration options (including environment variables) can be // tested separately from the user's environment. It is used exclusively -// in functions labelled testAccKubernetesProvider_*. +// in functions labelled testAccKubernetesProviderConfig_*. func testAccPreCheckInternal(t *testing.T) { ctx := context.TODO() unsetEnv(t) @@ -473,7 +473,7 @@ func requiredProviders() string { } // testAccProviderFactoriesInternal is a factory used for provider configuration testing. -// This should only be used for TestAccKubernetesProvider_ tests which need to +// This should only be used for TestAccKubernetesProviderConfig_ tests which need to // reference the provider instance itself. Other testing should use testAccProviderFactories. var testAccProviderFactoriesInternal = map[string]func() (*schema.Provider, error){ "kubernetes": func() (*schema.Provider, error) { From ce198a4320dac28a498fd4447b341e1abe95757b Mon Sep 17 00:00:00 2001 From: Stef Forrester Date: Sun, 14 Mar 2021 10:04:44 -0700 Subject: [PATCH 4/7] Remove lockfile --- kubernetes/test-infra/eks/.terraform.lock.hcl | 147 ------------------ 1 file changed, 147 deletions(-) delete mode 100644 kubernetes/test-infra/eks/.terraform.lock.hcl diff --git a/kubernetes/test-infra/eks/.terraform.lock.hcl b/kubernetes/test-infra/eks/.terraform.lock.hcl deleted file mode 100644 index a9b02f8227..0000000000 --- a/kubernetes/test-infra/eks/.terraform.lock.hcl +++ /dev/null @@ -1,147 +0,0 @@ -# This file is maintained automatically by "terraform init". -# Manual edits may be lost in future updates. - -provider "localhost/test/helm" { - version = "9.9.9" - constraints = "9.9.9" - hashes = [ - "h1:npZpS0MeIa75Fqq2LaEKcYZ8oi6rOogciOYH+oaCtvY=", - ] -} - -provider "localhost/test/kubernetes" { - version = "9.9.9" - constraints = "9.9.9" - hashes = [ - "h1:SWuBXYSfT0iDYpGWgBf/EhnzjCqlsuMQyFRl/co1Uyg=", - ] -} - -provider "registry.terraform.io/hashicorp/aws" { - version = "3.22.0" - constraints = ">= 3.22.0, 3.22.0" - hashes = [ - "h1:8aWXjFcmEi64P0TMHOCQXWws+/SmvJQrNvHlzdktKOM=", - "zh:4a9a66caf1964cdd3b61fb3ebb0da417195a5529cb8e496f266b0778335d11c8", - "zh:514f2f006ae68db715d86781673faf9483292deab235c7402ff306e0e92ea11a", - "zh:5277b61109fddb9011728f6650ef01a639a0590aeffe34ed7de7ba10d0c31803", - "zh:67784dc8c8375ab37103eea1258c3334ee92be6de033c2b37e3a2a65d0005142", - "zh:76d4c8be2ca4a3294fb51fb58de1fe03361d3bc403820270cc8e71a04c5fa806", - "zh:8f90b1cfdcf6e8fb1a9d0382ecaa5056a3a84c94e313fbf9e92c89de271cdede", - "zh:d0ac346519d0df124df89be2d803eb53f373434890f6ee3fb37112802f9eac59", - "zh:d6256feedada82cbfb3b1dd6dd9ad02048f23120ab50e6146a541cb11a108cc1", - "zh:db2fe0d2e77c02e9a74e1ed694aa352295a50283f9a1cf896e5be252af14e9f4", - "zh:eda61e889b579bd90046939a5b40cf5dc9031fb5a819fc3e4667a78bd432bdb2", - ] -} - -provider "registry.terraform.io/hashicorp/helm" { - version = "2.0.3" - hashes = [ - "h1:eUr4dHyxlcLmLja0wBgJC7t5bfHzbtACyuumKPuDrGs=", - "zh:154e0aa489e474e2eeb3de94be7666133faf6fd950712a640425b2bf3a81ee95", - "zh:16a2be6c4b61d0c5205c63816148c7ab0c8f56a75c05e8d897fa4d5cac0c029a", - "zh:189e47bc723f8c29bcfe2c1638d43b8148f614ea86e642f4b50b2acb4b760224", - "zh:3763901d3630213002cb8c70bb24c628cd29738ff6591585250ea8636264abd6", - "zh:4822f85e4700ea049384523d98de0ef7d83549844b13e94bbd544cec05557a9a", - "zh:62c5b87b09e0051bab0b712e3ad465fd53e66f9619dbe76ee23519d1087d8a05", - "zh:a0a6a842b11190dd1841e98bbb74961074e7ffb95984be5cc392df9f532d803e", - "zh:beac4e6806e77447e1018f3404a5fbf782d20d82a0d9b4a31e9bfc7d2bbecab6", - "zh:e1bbaa09bf4f4a91ec7606f84d2e0200a02e7b24d045e8b5daebd87d7a75b7ce", - "zh:ed1e05c50212d4f57435ccdd68cfb98d8395927c316df76d1dd6509566d3aeaa", - "zh:fdc687e16a964bb652ddb670f6832fdead25235eca551796cfed70ec07d94931", - ] -} - -provider "registry.terraform.io/hashicorp/kubernetes" { - version = "2.0.2" - constraints = ">= 1.11.1" - hashes = [ - "h1:PRfDnUFBD4ud7SgsMAa5S2Gd60FeriD1PWE6EifjXB0=", - "zh:4e66d509c828b0a2e599a567ad470bf85ebada62788aead87a8fb621301dec55", - "zh:55ca6466a82f60d2c9798d171edafacc9ea4991aa7aa32ed5d82d6831cf44542", - "zh:65741e6910c8b1322d9aef5dda4d98d1e6409aebc5514b518f46019cd06e1b47", - "zh:79456ca037c19983977285703f19f4b04f7eadcf8eb6af21f5ea615026271578", - "zh:7c39ced4dc44181296721715005e390021770077012c206ab4c209fb704b34d0", - "zh:86856c82a6444c19b3e3005e91408ac68eb010c9218c4c4119fc59300b107026", - "zh:999865090c72fa9b85c45e76b20839da51714ae429d1ab14b7d8ce66c2655abf", - "zh:a3ea0ae37c61b4bfe81f7a395fb7b5ba61564e7d716d7a191372c3c983271d13", - "zh:d9061861822933ebb2765fa691aeed2930ee495bfb6f72a5bdd88f43ccd9e038", - "zh:e04adbe0d5597d1fdd4f418be19c9df171f1d709009f63b8ce1239b71b4fa45a", - ] -} - -provider "registry.terraform.io/hashicorp/local" { - version = "2.1.0" - constraints = ">= 1.4.0" - hashes = [ - "h1:EYZdckuGU3n6APs97nS2LxZm3dDtGqyM4qaIvsmac8o=", - "zh:0f1ec65101fa35050978d483d6e8916664b7556800348456ff3d09454ac1eae2", - "zh:36e42ac19f5d68467aacf07e6adcf83c7486f2e5b5f4339e9671f68525fc87ab", - "zh:6db9db2a1819e77b1642ec3b5e95042b202aee8151a0256d289f2e141bf3ceb3", - "zh:719dfd97bb9ddce99f7d741260b8ece2682b363735c764cac83303f02386075a", - "zh:7598bb86e0378fd97eaa04638c1a4c75f960f62f69d3662e6d80ffa5a89847fe", - "zh:ad0a188b52517fec9eca393f1e2c9daea362b33ae2eb38a857b6b09949a727c1", - "zh:c46846c8df66a13fee6eff7dc5d528a7f868ae0dcf92d79deaac73cc297ed20c", - "zh:dc1a20a2eec12095d04bf6da5321f535351a594a636912361db20eb2a707ccc4", - "zh:e57ab4771a9d999401f6badd8b018558357d3cbdf3d33cc0c4f83e818ca8e94b", - "zh:ebdcde208072b4b0f8d305ebf2bfdc62c926e0717599dcf8ec2fd8c5845031c3", - "zh:ef34c52b68933bedd0868a13ccfd59ff1c820f299760b3c02e008dc95e2ece91", - ] -} - -provider "registry.terraform.io/hashicorp/null" { - version = "3.1.0" - constraints = ">= 2.1.0" - hashes = [ - "h1:vpC6bgUQoJ0znqIKVFevOdq+YQw42bRq0u+H3nto8nA=", - "zh:02a1675fd8de126a00460942aaae242e65ca3380b5bb192e8773ef3da9073fd2", - "zh:53e30545ff8926a8e30ad30648991ca8b93b6fa496272cd23b26763c8ee84515", - "zh:5f9200bf708913621d0f6514179d89700e9aa3097c77dac730e8ba6e5901d521", - "zh:9ebf4d9704faba06b3ec7242c773c0fbfe12d62db7d00356d4f55385fc69bfb2", - "zh:a6576c81adc70326e4e1c999c04ad9ca37113a6e925aefab4765e5a5198efa7e", - "zh:a8a42d13346347aff6c63a37cda9b2c6aa5cc384a55b2fe6d6adfa390e609c53", - "zh:c797744d08a5307d50210e0454f91ca4d1c7621c68740441cf4579390452321d", - "zh:cecb6a304046df34c11229f20a80b24b1603960b794d68361a67c5efe58e62b8", - "zh:e1371aa1e502000d9974cfaff5be4cfa02f47b17400005a16f14d2ef30dc2a70", - "zh:fc39cc1fe71234a0b0369d5c5c7f876c71b956d23d7d6f518289737a001ba69b", - "zh:fea4227271ebf7d9e2b61b89ce2328c7262acd9fd190e1fd6d15a591abfa848e", - ] -} - -provider "registry.terraform.io/hashicorp/random" { - version = "3.1.0" - constraints = ">= 2.1.0" - hashes = [ - "h1:BZMEPucF+pbu9gsPk0G0BHx7YP04+tKdq2MrRDF1EDM=", - "zh:2bbb3339f0643b5daa07480ef4397bd23a79963cc364cdfbb4e86354cb7725bc", - "zh:3cd456047805bf639fbf2c761b1848880ea703a054f76db51852008b11008626", - "zh:4f251b0eda5bb5e3dc26ea4400dba200018213654b69b4a5f96abee815b4f5ff", - "zh:7011332745ea061e517fe1319bd6c75054a314155cb2c1199a5b01fe1889a7e2", - "zh:738ed82858317ccc246691c8b85995bc125ac3b4143043219bd0437adc56c992", - "zh:7dbe52fac7bb21227acd7529b487511c91f4107db9cc4414f50d04ffc3cab427", - "zh:a3a9251fb15f93e4cfc1789800fc2d7414bbc18944ad4c5c98f466e6477c42bc", - "zh:a543ec1a3a8c20635cf374110bd2f87c07374cf2c50617eee2c669b3ceeeaa9f", - "zh:d9ab41d556a48bd7059f0810cf020500635bfc696c9fc3adab5ea8915c1d886b", - "zh:d9e13427a7d011dbd654e591b0337e6074eef8c3b9bb11b2e39eaaf257044fd7", - "zh:f7605bd1437752114baf601bdf6931debe6dc6bfe3006eb7e9bb9080931dca8a", - ] -} - -provider "registry.terraform.io/hashicorp/template" { - version = "2.2.0" - constraints = ">= 2.1.0" - hashes = [ - "h1:94qn780bi1qjrbC3uQtjJh3Wkfwd5+tTtJHOb7KTg9w=", - "zh:01702196f0a0492ec07917db7aaa595843d8f171dc195f4c988d2ffca2a06386", - "zh:09aae3da826ba3d7df69efeb25d146a1de0d03e951d35019a0f80e4f58c89b53", - "zh:09ba83c0625b6fe0a954da6fbd0c355ac0b7f07f86c91a2a97849140fea49603", - "zh:0e3a6c8e16f17f19010accd0844187d524580d9fdb0731f675ffcf4afba03d16", - "zh:45f2c594b6f2f34ea663704cc72048b212fe7d16fb4cfd959365fa997228a776", - "zh:77ea3e5a0446784d77114b5e851c970a3dde1e08fa6de38210b8385d7605d451", - "zh:8a154388f3708e3df5a69122a23bdfaf760a523788a5081976b3d5616f7d30ae", - "zh:992843002f2db5a11e626b3fc23dc0c87ad3729b3b3cff08e32ffb3df97edbde", - "zh:ad906f4cebd3ec5e43d5cd6dc8f4c5c9cc3b33d2243c89c5fc18f97f7277b51d", - "zh:c979425ddb256511137ecd093e23283234da0154b7fa8b21c2687182d9aea8b2", - ] -} From 211009c8039a4518282bb060648947f4332e5c4f Mon Sep 17 00:00:00 2001 From: Stef Forrester Date: Sun, 14 Mar 2021 10:25:53 -0700 Subject: [PATCH 5/7] run test lint fix --- .../data_source_kubernetes_secret_test.go | 3 +-- kubernetes/provider_test.go | 27 +++++++------------ kubernetes/resource_kubernetes_pod_test.go | 6 ++--- 3 files changed, 12 insertions(+), 24 deletions(-) diff --git a/kubernetes/data_source_kubernetes_secret_test.go b/kubernetes/data_source_kubernetes_secret_test.go index 4d2f9623f4..849381839b 100644 --- a/kubernetes/data_source_kubernetes_secret_test.go +++ b/kubernetes/data_source_kubernetes_secret_test.go @@ -84,8 +84,7 @@ func testAccKubernetesDataSourceSecretConfig_basic(name string) string { } func testAccKubernetesDataSourceSecretConfig_read() string { - return fmt.Sprintf(` -data "kubernetes_secret" "test" { + return fmt.Sprintf(`data "kubernetes_secret" "test" { metadata { name = "${kubernetes_secret.test.metadata.0.name}" } diff --git a/kubernetes/provider_test.go b/kubernetes/provider_test.go index a0e819341f..241ed76dc3 100644 --- a/kubernetes/provider_test.go +++ b/kubernetes/provider_test.go @@ -806,56 +806,47 @@ resource kubernetes_namespace "test" { } func providerConfig_config_path(path string) string { - return fmt.Sprintf(` - config_path = "%s" + return fmt.Sprintf(` config_path = "%s" `, path) } func providerConfig_config_context(context string) string { - return fmt.Sprintf(` - config_context = "%s" + return fmt.Sprintf(` config_context = "%s" `, context) } func providerConfig_config_paths(paths string) string { - return fmt.Sprintf(` - config_paths = %s + return fmt.Sprintf(` config_paths = %s `, paths) } func providerConfig_token(token string) string { - return fmt.Sprintf(` - token = "%s" + return fmt.Sprintf(` token = "%s" `, token) } func providerConfig_cluster_ca_certificate(ca_cert string) string { - return fmt.Sprintf(` - cluster_ca_certificate = "%s" + return fmt.Sprintf(` cluster_ca_certificate = "%s" `, ca_cert) } func providerConfig_client_cert(client_cert string) string { - return fmt.Sprintf(` - client_certificate = "%s" + return fmt.Sprintf(` client_certificate = "%s" `, client_cert) } func providerConfig_client_key(client_key string) string { - return fmt.Sprintf(` - client_key = "%s" + return fmt.Sprintf(` client_key = "%s" `, client_key) } func providerConfig_host(host string) string { - return fmt.Sprintf(` - host = "%s" + return fmt.Sprintf(` host = "%s" `, host) } func providerConfig_exec(clusterName string) string { - return fmt.Sprintf(` - exec { + return fmt.Sprintf(` exec { api_version = "client.authentication.k8s.io/v1alpha1" args = ["eks", "get-token", "--cluster-name", "%s"] command = "aws" diff --git a/kubernetes/resource_kubernetes_pod_test.go b/kubernetes/resource_kubernetes_pod_test.go index 116b7f8402..26fd542e53 100644 --- a/kubernetes/resource_kubernetes_pod_test.go +++ b/kubernetes/resource_kubernetes_pod_test.go @@ -2082,8 +2082,7 @@ func testAccKubernetesTerminationMessagePolicyWithFallBackToLogsOnErr(podName, i } func testAccKubernetesPodConfigEnableServiceLinks(podName, imageName string) string { - return fmt.Sprintf(` -resource "kubernetes_pod" "test" { + return fmt.Sprintf(`resource "kubernetes_pod" "test" { metadata { labels = { app = "pod_label" @@ -2395,8 +2394,7 @@ func testAccKubernetesPodConfig_afterUpdate(name, imageName string) string { } func testAccKubernetesPodTopologySpreadConstraintConfig(podName, imageName string) string { - return fmt.Sprintf(` -resource "kubernetes_pod" "test" { + return fmt.Sprintf(`resource "kubernetes_pod" "test" { metadata { name = "%s" } From 415a860b9c9d6afc8c30c6061512c805f3eba542 Mon Sep 17 00:00:00 2001 From: Stef Forrester Date: Mon, 19 Apr 2021 17:47:46 -0700 Subject: [PATCH 6/7] Add conflictswith warning level message --- kubernetes/provider.go | 163 ++++++++++++++++++++++++----------------- 1 file changed, 95 insertions(+), 68 deletions(-) diff --git a/kubernetes/provider.go b/kubernetes/provider.go index a2153cda76..d445d3b815 100644 --- a/kubernetes/provider.go +++ b/kubernetes/provider.go @@ -7,7 +7,6 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/logging" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/mitchellh/go-homedir" apimachineryschema "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/discovery" @@ -25,65 +24,80 @@ import ( ) func Provider() *schema.Provider { + conditionsMessage := "Specifying more than one authentication method can lead to unpredictable behavior." + + " This option will be removed in a future release. Please update your configuration." p := &schema.Provider{ Schema: map[string]*schema.Schema{ "host": { - Type: schema.TypeString, - Optional: true, - DefaultFunc: schema.EnvDefaultFunc("KUBE_HOST", nil), - Description: "The hostname (in form of URI) of Kubernetes master.", - ConflictsWith: []string{"config_path", "config_paths"}, - ValidateDiagFunc: validation.ToDiagFunc(validation.IsURLWithHTTPorHTTPS), + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("KUBE_HOST", nil), + Description: "The hostname (in form of URI) of Kubernetes master.", + ConflictsWith: []string{"config_path", "config_paths"}, + ConditionsMode: "warning", + ConditionsMessage: conditionsMessage, // TODO: enable this when AtLeastOneOf works with optional attributes. // https://github.com/hashicorp/terraform-plugin-sdk/issues/705 // AtLeastOneOf: []string{"token", "exec", "username", "password", "client_certificate", "client_key"}, }, "username": { - Type: schema.TypeString, - Optional: true, - DefaultFunc: schema.EnvDefaultFunc("KUBE_USER", nil), - Description: "The username to use for HTTP basic authentication when accessing the Kubernetes master endpoint.", - ConflictsWith: []string{"config_path", "config_paths", "exec", "token", "client_certificate", "client_key"}, - RequiredWith: []string{"password", "host"}, + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("KUBE_USER", nil), + Description: "The username to use for HTTP basic authentication when accessing the Kubernetes master endpoint.", + ConflictsWith: []string{"config_path", "config_paths", "exec", "token", "client_certificate", "client_key"}, + RequiredWith: []string{"password", "host"}, + ConditionsMode: "warning", + ConditionsMessage: conditionsMessage, }, "password": { - Type: schema.TypeString, - Optional: true, - DefaultFunc: schema.EnvDefaultFunc("KUBE_PASSWORD", nil), - Description: "The password to use for HTTP basic authentication when accessing the Kubernetes master endpoint.", - ConflictsWith: []string{"config_path", "config_paths", "exec", "token", "client_certificate", "client_key"}, - RequiredWith: []string{"username", "host"}, + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("KUBE_PASSWORD", nil), + Description: "The password to use for HTTP basic authentication when accessing the Kubernetes master endpoint.", + ConflictsWith: []string{"config_path", "config_paths", "exec", "token", "client_certificate", "client_key"}, + RequiredWith: []string{"username", "host"}, + ConditionsMode: "warning", + ConditionsMessage: conditionsMessage, }, "insecure": { - Type: schema.TypeBool, - Optional: true, - DefaultFunc: schema.EnvDefaultFunc("KUBE_INSECURE", nil), - Description: "Whether server should be accessed without verifying the TLS certificate.", - ConflictsWith: []string{"cluster_ca_certificate", "client_key", "client_certificate", "exec"}, + Type: schema.TypeBool, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("KUBE_INSECURE", nil), + Description: "Whether server should be accessed without verifying the TLS certificate.", + ConflictsWith: []string{"cluster_ca_certificate", "client_key", "client_certificate", "exec"}, + ConditionsMode: "warning", + ConditionsMessage: conditionsMessage, }, "client_certificate": { - Type: schema.TypeString, - Optional: true, - DefaultFunc: schema.EnvDefaultFunc("KUBE_CLIENT_CERT_DATA", nil), - Description: "PEM-encoded client certificate for TLS authentication.", - ConflictsWith: []string{"config_path", "config_paths", "username", "password", "insecure"}, - RequiredWith: []string{"client_key", "cluster_ca_certificate", "host"}, + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("KUBE_CLIENT_CERT_DATA", nil), + Description: "PEM-encoded client certificate for TLS authentication.", + ConflictsWith: []string{"config_path", "config_paths", "username", "password", "insecure"}, + RequiredWith: []string{"client_key", "cluster_ca_certificate", "host"}, + ConditionsMode: "warning", + ConditionsMessage: conditionsMessage, }, "client_key": { - Type: schema.TypeString, - Optional: true, - DefaultFunc: schema.EnvDefaultFunc("KUBE_CLIENT_KEY_DATA", nil), - Description: "PEM-encoded client certificate key for TLS authentication.", - ConflictsWith: []string{"config_path", "config_paths", "username", "password", "exec", "insecure"}, - RequiredWith: []string{"client_certificate", "cluster_ca_certificate", "host"}, + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("KUBE_CLIENT_KEY_DATA", nil), + Description: "PEM-encoded client certificate key for TLS authentication.", + ConflictsWith: []string{"config_path", "config_paths", "username", "password", "exec", "insecure"}, + RequiredWith: []string{"client_certificate", "cluster_ca_certificate", "host"}, + ConditionsMode: "warning", + ConditionsMessage: conditionsMessage, }, "cluster_ca_certificate": { - Type: schema.TypeString, - Optional: true, - DefaultFunc: schema.EnvDefaultFunc("KUBE_CLUSTER_CA_CERT_DATA", nil), - Description: "PEM-encoded root certificates bundle for TLS authentication.", - ConflictsWith: []string{"config_path", "config_paths", "insecure"}, - RequiredWith: []string{"host"}, + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("KUBE_CLUSTER_CA_CERT_DATA", nil), + Description: "PEM-encoded root certificates bundle for TLS authentication.", + ConflictsWith: []string{"config_path", "config_paths", "insecure"}, + RequiredWith: []string{"host"}, + ConditionsMode: "warning", + ConditionsMessage: conditionsMessage, // TODO: enable this when AtLeastOneOf works with optional attributes. // https://github.com/hashicorp/terraform-plugin-sdk/issues/705 // AtLeastOneOf: []string{"token", "exec", "client_certificate", "client_key"}, @@ -95,7 +109,9 @@ func Provider() *schema.Provider { Optional: true, Description: "A list of paths to kube config files. Can be set with KUBE_CONFIG_PATHS environment variable.", // config_paths conflicts with every attribute except for "insecure", since all of these options will be read from the kubeconfig. - ConflictsWith: []string{"config_path", "exec", "token", "host", "client_certificate", "client_key", "cluster_ca_certificate", "username", "password"}, + ConflictsWith: []string{"config_path", "exec", "token", "host", "client_certificate", "client_key", "cluster_ca_certificate", "username", "password"}, + ConditionsMode: "warning", + ConditionsMessage: conditionsMessage, }, "config_path": { Type: schema.TypeString, @@ -103,42 +119,51 @@ func Provider() *schema.Provider { DefaultFunc: schema.EnvDefaultFunc("KUBE_CONFIG_PATH", nil), Description: "Path to the kube config file. Can be set with KUBE_CONFIG_PATH.", // config_path conflicts with every attribute except for "insecure", since all of these options will be read from the kubeconfig. - ConflictsWith: []string{"config_paths", "exec", "token", "host", "client_certificate", "client_key", "cluster_ca_certificate", "username", "password"}, + ConflictsWith: []string{"config_paths", "exec", "token", "host", "client_certificate", "client_key", "cluster_ca_certificate", "username", "password"}, + ConditionsMode: "warning", + ConditionsMessage: conditionsMessage, }, "config_context": { - Type: schema.TypeString, - Optional: true, - DefaultFunc: schema.EnvDefaultFunc("KUBE_CTX", nil), - Description: "Context to choose from the kube config file. ", - ConflictsWith: []string{"exec", "token", "client_certificate", "client_key", "username", "password"}, + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("KUBE_CTX", nil), + Description: "Context to choose from the kube config file. ", + ConflictsWith: []string{"exec", "token", "client_certificate", "client_key", "username", "password"}, + ConditionsMode: "warning", + ConditionsMessage: "This functionality will be removed in a later release. Please update your configuration.", // TODO: enable this when AtLeastOneOf works with optional attributes. // AtLeastOneOf: []string{"config_path", "config_paths"}, }, "config_context_auth_info": { - Type: schema.TypeString, - Optional: true, - DefaultFunc: schema.EnvDefaultFunc("KUBE_CTX_AUTH_INFO", nil), - Description: "Authentication info context of the kube config (name of the kubeconfig user, --user flag in kubectl).", - ConflictsWith: []string{"exec", "token", "client_certificate", "client_key", "username", "password"}, + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("KUBE_CTX_AUTH_INFO", nil), + Description: "Authentication info context of the kube config (name of the kubeconfig user, --user flag in kubectl).", + ConflictsWith: []string{"exec", "token", "client_certificate", "client_key", "username", "password"}, + ConditionsMode: "warning", + ConditionsMessage: "This functionality will be removed in a later release. Please update your configuration.", // TODO: enable this when AtLeastOneOf works with optional attributes. // AtLeastOneOf: []string{"config_path", "config_paths"}, }, "config_context_cluster": { - Type: schema.TypeString, - Optional: true, - DefaultFunc: schema.EnvDefaultFunc("KUBE_CTX_CLUSTER", nil), - Description: "Cluster context of the kube config (name of the kubeconfig cluster, --cluster flag in kubectl).", - ConflictsWith: []string{"exec", "token", "client_certificate", "client_key", "username", "password"}, + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("KUBE_CTX_CLUSTER", nil), + Description: "Cluster context of the kube config (name of the kubeconfig cluster, --cluster flag in kubectl).", + ConflictsWith: []string{"exec", "token", "client_certificate", "client_key", "username", "password"}, + ConditionsMessage: "Specifying more than one authentication method can lead to unpredictable behavior. This option will be removed in a future release. Please update your configuration.", // TODO: enable this when AtLeastOneOf works with optional attributes. // AtLeastOneOf: []string{"config_path", "config_paths"}, }, "token": { - Type: schema.TypeString, - Optional: true, - DefaultFunc: schema.EnvDefaultFunc("KUBE_TOKEN", nil), - Description: "Bearer token for authenticating the Kubernetes API.", - ConflictsWith: []string{"config_path", "config_paths", "exec", "client_certificate", "client_key", "username", "password"}, - RequiredWith: []string{"host"}, + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("KUBE_TOKEN", nil), + Description: "Bearer token for authenticating the Kubernetes API.", + ConflictsWith: []string{"config_path", "config_paths", "exec", "client_certificate", "client_key", "username", "password"}, + ConditionsMode: "warning", + ConditionsMessage: "Specifying more than one authentication method can lead to unpredictable behavior. This option will be removed in a future release. Please update your configuration.", + RequiredWith: []string{"host"}, }, "exec": { Type: schema.TypeList, @@ -166,9 +191,11 @@ func Provider() *schema.Provider { }, }, }, - Description: "Configuration block to use an exec-based credential plugin, e.g. call an external command to receive user credentials.", - ConflictsWith: []string{"config_path", "config_paths", "token", "client_certificate", "client_key", "username", "password", "insecure"}, - RequiredWith: []string{"host", "cluster_ca_certificate"}, + Description: "Configuration block to use an exec-based credential plugin, e.g. call an external command to receive user credentials.", + ConflictsWith: []string{"config_path", "config_paths", "token", "client_certificate", "client_key", "username", "password", "insecure"}, + RequiredWith: []string{"host", "cluster_ca_certificate"}, + ConditionsMode: "warning", + ConditionsMessage: "Specifying more than one authentication method can lead to unpredictable behavior. This option will be removed in a future release. Please update your configuration.", }, }, From 0ef58a646258fa6b109b86f9bf83e2de7fd39290 Mon Sep 17 00:00:00 2001 From: Stef Forrester Date: Fri, 23 Apr 2021 14:12:04 -0700 Subject: [PATCH 7/7] Use new type for ConditionsMode --- kubernetes/provider.go | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/kubernetes/provider.go b/kubernetes/provider.go index d445d3b815..7e11df6c6c 100644 --- a/kubernetes/provider.go +++ b/kubernetes/provider.go @@ -34,7 +34,7 @@ func Provider() *schema.Provider { DefaultFunc: schema.EnvDefaultFunc("KUBE_HOST", nil), Description: "The hostname (in form of URI) of Kubernetes master.", ConflictsWith: []string{"config_path", "config_paths"}, - ConditionsMode: "warning", + ConditionsMode: schema.SchemaConditionsModeWarning, ConditionsMessage: conditionsMessage, // TODO: enable this when AtLeastOneOf works with optional attributes. // https://github.com/hashicorp/terraform-plugin-sdk/issues/705 @@ -47,7 +47,7 @@ func Provider() *schema.Provider { Description: "The username to use for HTTP basic authentication when accessing the Kubernetes master endpoint.", ConflictsWith: []string{"config_path", "config_paths", "exec", "token", "client_certificate", "client_key"}, RequiredWith: []string{"password", "host"}, - ConditionsMode: "warning", + ConditionsMode: schema.SchemaConditionsModeWarning, ConditionsMessage: conditionsMessage, }, "password": { @@ -57,7 +57,7 @@ func Provider() *schema.Provider { Description: "The password to use for HTTP basic authentication when accessing the Kubernetes master endpoint.", ConflictsWith: []string{"config_path", "config_paths", "exec", "token", "client_certificate", "client_key"}, RequiredWith: []string{"username", "host"}, - ConditionsMode: "warning", + ConditionsMode: schema.SchemaConditionsModeWarning, ConditionsMessage: conditionsMessage, }, "insecure": { @@ -66,7 +66,7 @@ func Provider() *schema.Provider { DefaultFunc: schema.EnvDefaultFunc("KUBE_INSECURE", nil), Description: "Whether server should be accessed without verifying the TLS certificate.", ConflictsWith: []string{"cluster_ca_certificate", "client_key", "client_certificate", "exec"}, - ConditionsMode: "warning", + ConditionsMode: schema.SchemaConditionsModeWarning, ConditionsMessage: conditionsMessage, }, "client_certificate": { @@ -76,7 +76,7 @@ func Provider() *schema.Provider { Description: "PEM-encoded client certificate for TLS authentication.", ConflictsWith: []string{"config_path", "config_paths", "username", "password", "insecure"}, RequiredWith: []string{"client_key", "cluster_ca_certificate", "host"}, - ConditionsMode: "warning", + ConditionsMode: schema.SchemaConditionsModeWarning, ConditionsMessage: conditionsMessage, }, "client_key": { @@ -86,7 +86,7 @@ func Provider() *schema.Provider { Description: "PEM-encoded client certificate key for TLS authentication.", ConflictsWith: []string{"config_path", "config_paths", "username", "password", "exec", "insecure"}, RequiredWith: []string{"client_certificate", "cluster_ca_certificate", "host"}, - ConditionsMode: "warning", + ConditionsMode: schema.SchemaConditionsModeWarning, ConditionsMessage: conditionsMessage, }, "cluster_ca_certificate": { @@ -96,7 +96,7 @@ func Provider() *schema.Provider { Description: "PEM-encoded root certificates bundle for TLS authentication.", ConflictsWith: []string{"config_path", "config_paths", "insecure"}, RequiredWith: []string{"host"}, - ConditionsMode: "warning", + ConditionsMode: schema.SchemaConditionsModeWarning, ConditionsMessage: conditionsMessage, // TODO: enable this when AtLeastOneOf works with optional attributes. // https://github.com/hashicorp/terraform-plugin-sdk/issues/705 @@ -110,7 +110,7 @@ func Provider() *schema.Provider { Description: "A list of paths to kube config files. Can be set with KUBE_CONFIG_PATHS environment variable.", // config_paths conflicts with every attribute except for "insecure", since all of these options will be read from the kubeconfig. ConflictsWith: []string{"config_path", "exec", "token", "host", "client_certificate", "client_key", "cluster_ca_certificate", "username", "password"}, - ConditionsMode: "warning", + ConditionsMode: schema.SchemaConditionsModeWarning, ConditionsMessage: conditionsMessage, }, "config_path": { @@ -120,7 +120,7 @@ func Provider() *schema.Provider { Description: "Path to the kube config file. Can be set with KUBE_CONFIG_PATH.", // config_path conflicts with every attribute except for "insecure", since all of these options will be read from the kubeconfig. ConflictsWith: []string{"config_paths", "exec", "token", "host", "client_certificate", "client_key", "cluster_ca_certificate", "username", "password"}, - ConditionsMode: "warning", + ConditionsMode: schema.SchemaConditionsModeWarning, ConditionsMessage: conditionsMessage, }, "config_context": { @@ -129,7 +129,7 @@ func Provider() *schema.Provider { DefaultFunc: schema.EnvDefaultFunc("KUBE_CTX", nil), Description: "Context to choose from the kube config file. ", ConflictsWith: []string{"exec", "token", "client_certificate", "client_key", "username", "password"}, - ConditionsMode: "warning", + ConditionsMode: schema.SchemaConditionsModeWarning, ConditionsMessage: "This functionality will be removed in a later release. Please update your configuration.", // TODO: enable this when AtLeastOneOf works with optional attributes. // AtLeastOneOf: []string{"config_path", "config_paths"}, @@ -140,7 +140,7 @@ func Provider() *schema.Provider { DefaultFunc: schema.EnvDefaultFunc("KUBE_CTX_AUTH_INFO", nil), Description: "Authentication info context of the kube config (name of the kubeconfig user, --user flag in kubectl).", ConflictsWith: []string{"exec", "token", "client_certificate", "client_key", "username", "password"}, - ConditionsMode: "warning", + ConditionsMode: schema.SchemaConditionsModeWarning, ConditionsMessage: "This functionality will be removed in a later release. Please update your configuration.", // TODO: enable this when AtLeastOneOf works with optional attributes. // AtLeastOneOf: []string{"config_path", "config_paths"}, @@ -151,6 +151,7 @@ func Provider() *schema.Provider { DefaultFunc: schema.EnvDefaultFunc("KUBE_CTX_CLUSTER", nil), Description: "Cluster context of the kube config (name of the kubeconfig cluster, --cluster flag in kubectl).", ConflictsWith: []string{"exec", "token", "client_certificate", "client_key", "username", "password"}, + ConditionsMode: schema.SchemaConditionsModeWarning, ConditionsMessage: "Specifying more than one authentication method can lead to unpredictable behavior. This option will be removed in a future release. Please update your configuration.", // TODO: enable this when AtLeastOneOf works with optional attributes. // AtLeastOneOf: []string{"config_path", "config_paths"}, @@ -161,7 +162,7 @@ func Provider() *schema.Provider { DefaultFunc: schema.EnvDefaultFunc("KUBE_TOKEN", nil), Description: "Bearer token for authenticating the Kubernetes API.", ConflictsWith: []string{"config_path", "config_paths", "exec", "client_certificate", "client_key", "username", "password"}, - ConditionsMode: "warning", + ConditionsMode: schema.SchemaConditionsModeWarning, ConditionsMessage: "Specifying more than one authentication method can lead to unpredictable behavior. This option will be removed in a future release. Please update your configuration.", RequiredWith: []string{"host"}, }, @@ -194,7 +195,7 @@ func Provider() *schema.Provider { Description: "Configuration block to use an exec-based credential plugin, e.g. call an external command to receive user credentials.", ConflictsWith: []string{"config_path", "config_paths", "token", "client_certificate", "client_key", "username", "password", "insecure"}, RequiredWith: []string{"host", "cluster_ca_certificate"}, - ConditionsMode: "warning", + ConditionsMode: schema.SchemaConditionsModeWarning, ConditionsMessage: "Specifying more than one authentication method can lead to unpredictable behavior. This option will be removed in a future release. Please update your configuration.", }, },