Add config_paths and drop KUBECONFIG env variable in kubernetes backend (#26997)
This commit is contained in:
parent
14336ae6f8
commit
fabdf0bea1
|
@ -6,11 +6,11 @@ import (
|
|||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/hashicorp/terraform/backend"
|
||||
"github.com/hashicorp/terraform/internal/legacy/helper/schema"
|
||||
"github.com/hashicorp/terraform/version"
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
k8sSchema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/dynamic"
|
||||
|
@ -114,16 +114,17 @@ func New() backend.Backend {
|
|||
DefaultFunc: schema.EnvDefaultFunc("KUBE_CLUSTER_CA_CERT_DATA", ""),
|
||||
Description: "PEM-encoded root certificates bundle for TLS authentication.",
|
||||
},
|
||||
"config_paths": {
|
||||
Type: schema.TypeList,
|
||||
Elem: &schema.Schema{Type: schema.TypeString},
|
||||
Optional: true,
|
||||
Description: "A list of paths to kube config files. Can be set with KUBE_CONFIG_PATHS environment variable.",
|
||||
},
|
||||
"config_path": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
DefaultFunc: schema.MultiEnvDefaultFunc(
|
||||
[]string{
|
||||
"KUBE_CONFIG",
|
||||
"KUBECONFIG",
|
||||
},
|
||||
"~/.kube/config"),
|
||||
Description: "Path to the kube config file, defaults to ~/.kube/config",
|
||||
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.",
|
||||
},
|
||||
"config_context": {
|
||||
Type: schema.TypeString,
|
||||
|
@ -285,15 +286,7 @@ func getInitialConfig(data *schema.ResourceData) (*restclient.Config, error) {
|
|||
var cfg *restclient.Config
|
||||
var err error
|
||||
|
||||
c := &cli.BasicUi{Writer: os.Stdout}
|
||||
|
||||
inCluster := data.Get("in_cluster_config").(bool)
|
||||
cf := data.Get("load_config_file").(bool)
|
||||
|
||||
if !inCluster && !cf {
|
||||
c.Output(noConfigError)
|
||||
}
|
||||
|
||||
if inCluster {
|
||||
cfg, err = restclient.InClusterConfig()
|
||||
if err != nil {
|
||||
|
@ -313,13 +306,34 @@ func getInitialConfig(data *schema.ResourceData) (*restclient.Config, error) {
|
|||
}
|
||||
|
||||
func tryLoadingConfigFile(d *schema.ResourceData) (*restclient.Config, error) {
|
||||
path, err := homedir.Expand(d.Get("config_path").(string))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
loader := &clientcmd.ClientConfigLoadingRules{}
|
||||
|
||||
configPaths := []string{}
|
||||
if v, ok := d.Get("config_path").(string); ok && v != "" {
|
||||
configPaths = []string{v}
|
||||
} else if v, ok := d.Get("config_paths").([]interface{}); ok && len(v) > 0 {
|
||||
for _, p := range v {
|
||||
configPaths = append(configPaths, p.(string))
|
||||
}
|
||||
} else if v := os.Getenv("KUBE_CONFIG_PATHS"); v != "" {
|
||||
configPaths = filepath.SplitList(v)
|
||||
}
|
||||
|
||||
loader := &clientcmd.ClientConfigLoadingRules{
|
||||
ExplicitPath: path,
|
||||
expandedPaths := []string{}
|
||||
for _, p := range configPaths {
|
||||
path, err := homedir.Expand(p)
|
||||
if err != nil {
|
||||
log.Printf("[DEBUG] Could not expand path: %s", err)
|
||||
return nil, err
|
||||
}
|
||||
log.Printf("[DEBUG] Using kubeconfig: %s", path)
|
||||
expandedPaths = append(expandedPaths, path)
|
||||
}
|
||||
|
||||
if len(expandedPaths) == 1 {
|
||||
loader.ExplicitPath = expandedPaths[0]
|
||||
} else {
|
||||
loader.Precedence = expandedPaths
|
||||
}
|
||||
|
||||
overrides := &clientcmd.ConfigOverrides{}
|
||||
|
@ -367,13 +381,13 @@ func tryLoadingConfigFile(d *schema.ResourceData) (*restclient.Config, error) {
|
|||
cfg, err := cc.ClientConfig()
|
||||
if err != nil {
|
||||
if pathErr, ok := err.(*os.PathError); ok && os.IsNotExist(pathErr.Err) {
|
||||
log.Printf("[INFO] Unable to load config file as it doesn't exist at %q", path)
|
||||
log.Printf("[INFO] Unable to load config file as it doesn't exist at %q", pathErr.Path)
|
||||
return nil, nil
|
||||
}
|
||||
return nil, fmt.Errorf("Failed to load config (%s%s): %s", path, ctxSuffix, err)
|
||||
return nil, fmt.Errorf("Failed to initialize kubernetes configuration: %s", err)
|
||||
}
|
||||
|
||||
log.Printf("[INFO] Successfully loaded config file (%s%s)", path, ctxSuffix)
|
||||
log.Printf("[INFO] Successfully initialized config")
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/util/validation"
|
||||
"k8s.io/client-go/dynamic"
|
||||
_ "k8s.io/client-go/plugin/pkg/client/auth" // Import to initialize client auth plugins.
|
||||
"k8s.io/utils/pointer"
|
||||
|
||||
coordinationv1 "k8s.io/api/coordination/v1"
|
||||
|
|
|
@ -20,18 +20,18 @@ Stores the state in a [Kubernetes secret](https://kubernetes.io/docs/concepts/co
|
|||
terraform {
|
||||
backend "kubernetes" {
|
||||
secret_suffix = "state"
|
||||
load_config_file = true
|
||||
config_path = "~/.kube/config"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This assumes the user/service account running terraform has [permissions](https://kubernetes.io/docs/reference/access-authn-authz/authorization/) to read/write secrets in the [namespace](https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/) used to store the secret.
|
||||
|
||||
If the `load_config_file` flag is set the backend will attempt to use a [kubeconfig file](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/) to gain access to the cluster.
|
||||
If the `config_path` or `config_paths` attribute is set the backend will attempt to use a [kubeconfig file](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/) to gain access to the cluster.
|
||||
|
||||
If the `in_cluster_config` flag is set the backend will attempt to use a [service account](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/) to access the cluster. This can be used if Terraform is being run from within a pod running in the Kubernetes cluster.
|
||||
|
||||
For most use cases either `in_cluster_config` or `load_config_file` will need to be set to `true`. If both flags are set the configuration from `load_config_file` will be used.
|
||||
For most use cases either `in_cluster_config`, `config_path`, or `config_paths` will need to be set. If all flags are set the configuration at `config_path` will be used.
|
||||
|
||||
Note that for the access credentials we recommend using a [partial configuration](/docs/language/settings/backends/configuration.html#partial-configuration).
|
||||
|
||||
|
@ -56,7 +56,6 @@ The following configuration options are supported:
|
|||
* `labels` - (Optional) Map of additional labels to be applied to the secret and lease.
|
||||
* `namespace` - (Optional) Namespace to store the secret and lease in. Can be sourced from `KUBE_NAMESPACE`.
|
||||
* `in_cluster_config` - (Optional) Used to authenticate to the cluster from inside a pod. Can be sourced from `KUBE_IN_CLUSTER_CONFIG`.
|
||||
* `load_config_file` - (Optional) Use a kubeconfig file to access the cluster. Can be sourced from `KUBE_LOAD_CONFIG_FILE`.
|
||||
* `host` - (Optional) The hostname (in form of URI) of Kubernetes master. Can be sourced from `KUBE_HOST`. Defaults to `https://localhost`.
|
||||
* `username` - (Optional) The username to use for HTTP basic authentication when accessing the Kubernetes master endpoint. Can be sourced from `KUBE_USER`.
|
||||
* `password` - (Optional) The password to use for HTTP basic authentication when accessing the Kubernetes master endpoint. Can be sourced from `KUBE_PASSWORD`.
|
||||
|
@ -64,7 +63,8 @@ The following configuration options 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` or `KUBECONFIG`. Defaults to `~/.kube/config`.
|
||||
* `config_path` - (Optional) Path to the kube config file. Can be sourced from `KUBE_CONFIG_PATH`.
|
||||
* `config_paths` - (Optional) List of paths to kube config files. Can be sourced from `KUBE_CONFIG_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`.
|
||||
|
|
Loading…
Reference in New Issue