185 lines
5.3 KiB
Go
185 lines
5.3 KiB
Go
/*
|
|
Copyright 2018 The Kubernetes 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 pluginutils
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
"time"
|
|
|
|
restclient "k8s.io/client-go/rest"
|
|
"k8s.io/client-go/tools/clientcmd"
|
|
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
|
)
|
|
|
|
// InitClientAndConfig uses the KUBECONFIG environment variable to create
|
|
// a new rest client and config object based on the existing kubectl config
|
|
// and options passed from the plugin framework via environment variables
|
|
func InitClientAndConfig() (*restclient.Config, clientcmd.ClientConfig, error) {
|
|
// resolve kubeconfig location, prioritizing the --config global flag,
|
|
// then the value of the KUBECONFIG env var (if any), and defaulting
|
|
// to ~/.kube/config as a last resort.
|
|
home := os.Getenv("HOME")
|
|
if runtime.GOOS == "windows" {
|
|
home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
|
|
if home == "" {
|
|
home = os.Getenv("USERPROFILE")
|
|
}
|
|
}
|
|
kubeconfig := filepath.Join(home, ".kube", "config")
|
|
|
|
kubeconfigEnv := os.Getenv("KUBECONFIG")
|
|
if len(kubeconfigEnv) > 0 {
|
|
kubeconfig = kubeconfigEnv
|
|
}
|
|
|
|
configFile := os.Getenv("KUBECTL_PLUGINS_GLOBAL_FLAG_CONFIG")
|
|
kubeConfigFile := os.Getenv("KUBECTL_PLUGINS_GLOBAL_FLAG_KUBECONFIG")
|
|
if len(configFile) > 0 {
|
|
kubeconfig = configFile
|
|
} else if len(kubeConfigFile) > 0 {
|
|
kubeconfig = kubeConfigFile
|
|
}
|
|
|
|
if len(kubeconfig) == 0 {
|
|
return nil, nil, fmt.Errorf("error initializing config. The KUBECONFIG environment variable must be defined.")
|
|
}
|
|
|
|
config, err := configFromPath(kubeconfig)
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("error obtaining kubectl config: %v", err)
|
|
}
|
|
client, err := config.ClientConfig()
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("the provided credentials %q could not be used: %v", kubeconfig, err)
|
|
}
|
|
|
|
err = applyGlobalOptionsToConfig(client)
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("error processing global plugin options: %v", err)
|
|
}
|
|
|
|
return client, config, nil
|
|
}
|
|
|
|
func configFromPath(path string) (clientcmd.ClientConfig, error) {
|
|
rules := &clientcmd.ClientConfigLoadingRules{ExplicitPath: path}
|
|
credentials, err := rules.Load()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("the provided credentials %q could not be loaded: %v", path, err)
|
|
}
|
|
|
|
overrides := &clientcmd.ConfigOverrides{
|
|
Context: clientcmdapi.Context{
|
|
Namespace: os.Getenv("KUBECTL_PLUGINS_GLOBAL_FLAG_NAMESPACE"),
|
|
},
|
|
}
|
|
|
|
var cfg clientcmd.ClientConfig
|
|
context := os.Getenv("KUBECTL_PLUGINS_GLOBAL_FLAG_CONTEXT")
|
|
if len(context) > 0 {
|
|
rules := clientcmd.NewDefaultClientConfigLoadingRules()
|
|
cfg = clientcmd.NewNonInteractiveClientConfig(*credentials, context, overrides, rules)
|
|
} else {
|
|
cfg = clientcmd.NewDefaultClientConfig(*credentials, overrides)
|
|
}
|
|
|
|
return cfg, nil
|
|
}
|
|
|
|
func applyGlobalOptionsToConfig(config *restclient.Config) error {
|
|
// impersonation config
|
|
impersonateUser := os.Getenv("KUBECTL_PLUGINS_GLOBAL_FLAG_AS")
|
|
if len(impersonateUser) > 0 {
|
|
config.Impersonate.UserName = impersonateUser
|
|
}
|
|
|
|
impersonateGroup := os.Getenv("KUBECTL_PLUGINS_GLOBAL_FLAG_AS_GROUP")
|
|
if len(impersonateGroup) > 0 {
|
|
impersonateGroupJSON := []string{}
|
|
err := json.Unmarshal([]byte(impersonateGroup), &impersonateGroupJSON)
|
|
if err != nil {
|
|
return errors.New(fmt.Sprintf("error parsing global option %q: %v", "--as-group", err))
|
|
}
|
|
if len(impersonateGroupJSON) > 0 {
|
|
config.Impersonate.Groups = impersonateGroupJSON
|
|
}
|
|
}
|
|
|
|
// tls config
|
|
caFile := os.Getenv("KUBECTL_PLUGINS_GLOBAL_FLAG_CERTIFICATE_AUTHORITY")
|
|
if len(caFile) > 0 {
|
|
config.TLSClientConfig.CAFile = caFile
|
|
}
|
|
|
|
clientCertFile := os.Getenv("KUBECTL_PLUGINS_GLOBAL_FLAG_CLIENT_CERTIFICATE")
|
|
if len(clientCertFile) > 0 {
|
|
config.TLSClientConfig.CertFile = clientCertFile
|
|
}
|
|
|
|
clientKey := os.Getenv("KUBECTL_PLUGINS_GLOBAL_FLAG_CLIENT_KEY")
|
|
if len(clientKey) > 0 {
|
|
config.TLSClientConfig.KeyFile = clientKey
|
|
}
|
|
|
|
cluster := os.Getenv("KUBECTL_PLUGINS_GLOBAL_FLAG_CLUSTER")
|
|
if len(cluster) > 0 {
|
|
// TODO(jvallejo): figure out how to override kubeconfig options
|
|
}
|
|
|
|
user := os.Getenv("KUBECTL_PLUGINS_GLOBAL_FLAG_USER")
|
|
if len(user) > 0 {
|
|
// TODO(jvallejo): figure out how to override kubeconfig options
|
|
}
|
|
|
|
// user / misc request config
|
|
requestTimeout := os.Getenv("KUBECTL_PLUGINS_GLOBAL_FLAG_REQUEST_TIMEOUT")
|
|
if len(requestTimeout) > 0 {
|
|
t, err := time.ParseDuration(requestTimeout)
|
|
if err != nil {
|
|
return errors.New(fmt.Sprintf("%v", err))
|
|
}
|
|
config.Timeout = t
|
|
}
|
|
|
|
server := os.Getenv("KUBECTL_PLUGINS_GLOBAL_FLAG_SERVER")
|
|
if len(server) > 0 {
|
|
config.ServerName = server
|
|
}
|
|
|
|
token := os.Getenv("KUBECTL_PLUGINS_GLOBAL_FLAG_TOKEN")
|
|
if len(token) > 0 {
|
|
config.BearerToken = token
|
|
}
|
|
|
|
username := os.Getenv("KUBECTL_PLUGINS_GLOBAL_FLAG_USERNAME")
|
|
if len(username) > 0 {
|
|
config.Username = username
|
|
}
|
|
|
|
password := os.Getenv("KUBECTL_PLUGINS_GLOBAL_FLAG_PASSWORD")
|
|
if len(password) > 0 {
|
|
config.Password = password
|
|
}
|
|
|
|
return nil
|
|
}
|