kubectl/pkg/pluginutils/plugin_client.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
}