2020-10-15 10:48:41 -07:00
|
|
|
package main
|
|
|
|
|
2021-02-10 18:23:00 -08:00
|
|
|
import (
|
2022-01-26 01:23:18 -08:00
|
|
|
"oh-my-posh/environment"
|
2022-01-26 04:53:35 -08:00
|
|
|
"oh-my-posh/properties"
|
2021-11-21 07:02:51 -08:00
|
|
|
"path/filepath"
|
|
|
|
|
|
|
|
"gopkg.in/yaml.v3"
|
2021-02-10 18:23:00 -08:00
|
|
|
)
|
|
|
|
|
2021-11-21 07:02:51 -08:00
|
|
|
// Whether to use kubectl or read kubeconfig ourselves
|
2022-01-26 04:53:35 -08:00
|
|
|
const ParseKubeConfig properties.Property = "parse_kubeconfig"
|
2021-11-21 07:02:51 -08:00
|
|
|
|
2020-10-15 10:48:41 -07:00
|
|
|
type kubectl struct {
|
2022-01-26 04:53:35 -08:00
|
|
|
props properties.Properties
|
2022-01-26 01:23:18 -08:00
|
|
|
env environment.Environment
|
|
|
|
|
2021-11-21 07:02:51 -08:00
|
|
|
Context string
|
2022-01-26 01:23:18 -08:00
|
|
|
|
2021-12-17 11:54:43 -08:00
|
|
|
KubeContext
|
2021-11-21 07:02:51 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
type KubeConfig struct {
|
|
|
|
CurrentContext string `yaml:"current-context"`
|
|
|
|
Contexts []struct {
|
2021-12-17 11:54:43 -08:00
|
|
|
Context *KubeContext `yaml:"context"`
|
|
|
|
Name string `yaml:"name"`
|
2021-11-21 07:02:51 -08:00
|
|
|
} `yaml:"contexts"`
|
2020-10-15 10:48:41 -07:00
|
|
|
}
|
|
|
|
|
2021-12-17 11:54:43 -08:00
|
|
|
type KubeContext struct {
|
|
|
|
Cluster string `yaml:"cluster"`
|
2022-01-17 04:16:04 -08:00
|
|
|
User string `yaml:"user"`
|
2021-12-17 11:54:43 -08:00
|
|
|
Namespace string `yaml:"namespace"`
|
|
|
|
}
|
|
|
|
|
2022-01-23 12:37:51 -08:00
|
|
|
func (k *kubectl) template() string {
|
|
|
|
return "{{ .Context }}{{ if .Namespace }} :: {{ .Namespace }}{{ end }}"
|
2020-10-15 10:48:41 -07:00
|
|
|
}
|
|
|
|
|
2022-01-26 04:53:35 -08:00
|
|
|
func (k *kubectl) init(props properties.Properties, env environment.Environment) {
|
2020-10-15 10:48:41 -07:00
|
|
|
k.props = props
|
|
|
|
k.env = env
|
|
|
|
}
|
|
|
|
|
|
|
|
func (k *kubectl) enabled() bool {
|
2022-01-26 04:09:21 -08:00
|
|
|
parseKubeConfig := k.props.GetBool(ParseKubeConfig, false)
|
2021-11-21 07:02:51 -08:00
|
|
|
if parseKubeConfig {
|
|
|
|
return k.doParseKubeConfig()
|
|
|
|
}
|
|
|
|
return k.doCallKubectl()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (k *kubectl) doParseKubeConfig() bool {
|
|
|
|
// Follow kubectl search rules (see https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/#the-kubeconfig-environment-variable)
|
|
|
|
// TL;DR: KUBECONFIG can contain a list of files. If it's empty ~/.kube/config is used. First file in list wins when merging keys.
|
2022-01-23 12:37:51 -08:00
|
|
|
kubeconfigs := filepath.SplitList(k.env.Getenv("KUBECONFIG"))
|
2021-11-21 07:02:51 -08:00
|
|
|
if len(kubeconfigs) == 0 {
|
2022-01-23 12:37:51 -08:00
|
|
|
kubeconfigs = []string{filepath.Join(k.env.Home(), ".kube/config")}
|
2021-11-21 07:02:51 -08:00
|
|
|
}
|
2021-12-17 11:54:43 -08:00
|
|
|
contexts := make(map[string]*KubeContext)
|
2021-11-21 07:02:51 -08:00
|
|
|
k.Context = ""
|
|
|
|
for _, kubeconfig := range kubeconfigs {
|
|
|
|
if len(kubeconfig) == 0 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2022-01-23 12:37:51 -08:00
|
|
|
content := k.env.FileContent(kubeconfig)
|
2021-11-21 07:02:51 -08:00
|
|
|
|
|
|
|
var config KubeConfig
|
|
|
|
err := yaml.Unmarshal([]byte(content), &config)
|
|
|
|
if err != nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, context := range config.Contexts {
|
|
|
|
if _, exists := contexts[context.Name]; !exists {
|
|
|
|
contexts[context.Name] = context.Context
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(k.Context) == 0 {
|
|
|
|
k.Context = config.CurrentContext
|
|
|
|
}
|
|
|
|
|
|
|
|
context, exists := contexts[k.Context]
|
2021-12-17 11:54:43 -08:00
|
|
|
if !exists {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if context != nil {
|
|
|
|
k.KubeContext = *context
|
2021-11-21 07:02:51 -08:00
|
|
|
}
|
2021-12-17 11:54:43 -08:00
|
|
|
return true
|
2021-11-21 07:02:51 -08:00
|
|
|
}
|
|
|
|
|
2022-01-26 04:53:35 -08:00
|
|
|
displayError := k.props.GetBool(properties.DisplayError, false)
|
2021-11-21 07:02:51 -08:00
|
|
|
if !displayError {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
k.setError("KUBECONFIG ERR")
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
func (k *kubectl) doCallKubectl() bool {
|
2021-01-05 04:05:37 -08:00
|
|
|
cmd := "kubectl"
|
2022-01-23 12:37:51 -08:00
|
|
|
if !k.env.HasCommand(cmd) {
|
2020-10-15 10:48:41 -07:00
|
|
|
return false
|
|
|
|
}
|
2022-01-23 12:37:51 -08:00
|
|
|
result, err := k.env.RunCommand(cmd, "config", "view", "--output", "yaml", "--minify")
|
2022-01-26 04:53:35 -08:00
|
|
|
displayError := k.props.GetBool(properties.DisplayError, false)
|
2021-02-12 12:39:20 -08:00
|
|
|
if err != nil && displayError {
|
2021-11-21 07:02:51 -08:00
|
|
|
k.setError("KUBECTL ERR")
|
2021-02-10 18:23:00 -08:00
|
|
|
return true
|
|
|
|
}
|
2021-02-12 12:39:20 -08:00
|
|
|
if err != nil {
|
|
|
|
return false
|
|
|
|
}
|
2021-02-10 18:23:00 -08:00
|
|
|
|
2021-12-17 11:54:43 -08:00
|
|
|
var config KubeConfig
|
|
|
|
err = yaml.Unmarshal([]byte(result), &config)
|
|
|
|
if err != nil {
|
2021-12-15 10:06:08 -08:00
|
|
|
return false
|
|
|
|
}
|
2021-12-17 11:54:43 -08:00
|
|
|
k.Context = config.CurrentContext
|
|
|
|
if len(config.Contexts) > 0 {
|
|
|
|
k.KubeContext = *config.Contexts[0].Context
|
|
|
|
}
|
|
|
|
return true
|
2021-11-21 07:02:51 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (k *kubectl) setError(message string) {
|
|
|
|
if len(k.Context) == 0 {
|
|
|
|
k.Context = message
|
|
|
|
}
|
|
|
|
k.Namespace = message
|
2022-01-17 04:16:04 -08:00
|
|
|
k.User = message
|
2021-11-21 07:02:51 -08:00
|
|
|
k.Cluster = message
|
2020-10-15 10:48:41 -07:00
|
|
|
}
|