feat: add flags --kubeconfig-json (#694)

This commit is contained in:
naison
2025-08-09 22:29:05 +08:00
committed by GitHub
parent 5b0758be69
commit d2a6d78331
5 changed files with 111 additions and 3 deletions

View File

@@ -61,6 +61,7 @@ func CmdAlias(f cmdutil.Factory) *cobra.Command {
If you have following config in your ~/.kubevpn/config.yaml
Name: dev
Description: This is dev k8s environment
Needs: jumper
Flags:
- connect
@@ -69,12 +70,21 @@ func CmdAlias(f cmdutil.Factory) *cobra.Command {
---
Name: jumper
Description: This is jumper k8s environment
Flags:
- connect
- --kubeconfig=~/.kube/jumper_config
- --namespace=test
- --extra-hosts=xxx.com
Name: all-in-one
Description: use special flags '--kubeconfig-json', no need to special kubeconfig path
Flags:
- connect
- --kubeconfig-json={"apiVersion":"v1","clusters":[{"cluster":{"certificate-authority-data":"LS0tLS1CRU..."}}]}
- --namespace=test
- --extra-hosts=xxx.com
Config file support three field: Name,Needs,Flags
# Use kubevpn alias config to simply execute command, connect to cluster network by order: jumper --> dev
@@ -82,6 +92,9 @@ func CmdAlias(f cmdutil.Factory) *cobra.Command {
# kubevpn alias jumper, just connect to cluster jumper
kubevpn alias jumper
# support special flags '--kubeconfig-json', it will save kubeconfig into ~/.kubevpn/temp/[ALIAS_NAME]
kubevpn alias all-in-one
`)),
PreRunE: func(cmd *cobra.Command, args []string) (err error) {
if localFile != "" {
@@ -100,6 +113,10 @@ func CmdAlias(f cmdutil.Factory) *cobra.Command {
return err
}
for _, conf := range configs {
err = ParseArgs(cmd, &conf)
if err != nil {
return err
}
c := exec.Command(name, conf.Flags...)
c.Stdout = os.Stdout
c.Stdin = os.Stdin

View File

@@ -5,6 +5,7 @@ import (
"strings"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/client-go/rest"
restclient "k8s.io/client-go/rest"
@@ -16,6 +17,7 @@ import (
"k8s.io/utils/ptr"
"github.com/wencaiwulue/kubevpn/v2/pkg/config"
"github.com/wencaiwulue/kubevpn/v2/pkg/util"
)
func NewKubeVPNCommand() *cobra.Command {
@@ -97,8 +99,13 @@ func NewKubeVPNCommand() *cobra.Command {
return cmd
}
func AddKubeconfigJsonFlag(flags *pflag.FlagSet, kubeconfigJson *string) {
flags.StringVar(kubeconfigJson, "kubeconfig-json", ptr.Deref[string](kubeconfigJson, ""), "Json format of kubeconfig to use for CLI requests.")
}
type warp struct {
*genericclioptions.ConfigFlags
KubeconfigJson string
}
func (f *warp) ToRawKubeConfigLoader() clientcmd.ClientConfig {
@@ -106,5 +113,11 @@ func (f *warp) ToRawKubeConfigLoader() clientcmd.ClientConfig {
home := homedir.HomeDir()
f.KubeConfig = ptr.To(strings.Replace(*f.KubeConfig, "~", home, 1))
}
if strings.TrimSpace(f.KubeconfigJson) != "" {
path, err := util.ConvertToTempKubeconfigFile([]byte(f.KubeconfigJson))
if err == nil {
f.KubeConfig = ptr.To(path)
}
}
return f.ConfigFlags.ToRawKubeConfigLoader()
}

View File

@@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"strings"
"github.com/liggitt/tabwriter"
@@ -233,9 +234,11 @@ func GetConnectionIDByConfig(cmd *cobra.Command, config Config) (string, error)
handler.AddExtraRoute(flags, &handler.ExtraRouteInfo{})
configFlags := genericclioptions.NewConfigFlags(true)
configFlags.AddFlags(flags)
matchVersionFlags := cmdutil.NewMatchVersionFlags(&warp{ConfigFlags: configFlags})
var kubeconfigJson string
AddKubeconfigJsonFlag(flags, &kubeconfigJson)
matchVersionFlags := cmdutil.NewMatchVersionFlags(&warp{ConfigFlags: configFlags, KubeconfigJson: kubeconfigJson})
matchVersionFlags.AddFlags(flags)
factory := cmdutil.NewFactory(matchVersionFlags)
f := cmdutil.NewFactory(matchVersionFlags)
for _, command := range cmd.Parent().Commands() {
command.Flags().VisitAll(func(f *flag.Flag) {
@@ -249,7 +252,7 @@ func GetConnectionIDByConfig(cmd *cobra.Command, config Config) (string, error)
_ = flags.Set(flag.Name, value)
return nil
})
bytes, ns, err := util.ConvertToKubeConfigBytes(factory)
bytes, ns, err := util.ConvertToKubeConfigBytes(f)
if err != nil {
return "", err
}
@@ -275,3 +278,56 @@ func GetConnectionIDByConfig(cmd *cobra.Command, config Config) (string, error)
}
return id, nil
}
func ParseArgs(cmd *cobra.Command, conf *Config) error {
var str string
for i := 0; i < len(conf.Flags); i++ {
kubeconfigJson, err := parseKubeconfigJson(cmd, []string{conf.Flags[i]})
if err != nil {
return err
}
if kubeconfigJson != "" {
str = kubeconfigJson
conf.Flags = append(conf.Flags[:i], conf.Flags[i+1:]...)
i--
}
}
if str == "" {
return nil
}
file, err := util.ConvertToKubeconfigFile([]byte(str), filepath.Join(config.GetTempPath(), conf.Name))
if err != nil {
return err
}
conf.Flags = append(conf.Flags, fmt.Sprintf("%s=%s", "--kubeconfig", file))
return nil
}
func parseKubeconfigJson(cmd *cobra.Command, args []string) (string, error) {
flags := flag.NewFlagSet("", flag.ContinueOnError)
var sshConf = &pkgssh.SshConfig{}
pkgssh.AddSshFlags(flags, sshConf)
handler.AddExtraRoute(flags, &handler.ExtraRouteInfo{})
configFlags := genericclioptions.NewConfigFlags(true)
configFlags.AddFlags(flags)
var kubeconfigJson string
AddKubeconfigJsonFlag(flags, &kubeconfigJson)
matchVersionFlags := cmdutil.NewMatchVersionFlags(&warp{ConfigFlags: configFlags})
matchVersionFlags.AddFlags(flags)
for _, command := range cmd.Parent().Commands() {
command.Flags().VisitAll(func(f *flag.Flag) {
if flags.Lookup(f.Name) == nil && flags.ShorthandLookup(f.Shorthand) == nil {
flags.AddFlag(f)
}
})
}
err := flags.ParseAll(args, func(flag *flag.Flag, value string) error {
_ = flags.Set(flag.Name, value)
return nil
})
return kubeconfigJson, err
}

View File

@@ -4,6 +4,7 @@
# Just keep simple
Name: dev
Description: This is dev k8s environment, needs jump by qa env
Needs: qa
Flags:
- connect
@@ -13,6 +14,7 @@ Flags:
---
Name: qa
Description: This is QA k8s environment
Flags:
- connect
- --kubeconfig=~/.kube/jumper_config

View File

@@ -152,6 +152,26 @@ func ConvertToTempKubeconfigFile(kubeconfigBytes []byte) (string, error) {
return temp.Name(), nil
}
func ConvertToKubeconfigFile(kubeconfigBytes []byte, filename string) (string, error) {
f, err := os.Create(filename)
if err != nil {
return "", err
}
_, err = f.Write(kubeconfigBytes)
if err != nil {
return "", err
}
err = f.Chmod(0644)
if err != nil {
return "", err
}
err = f.Close()
if err != nil {
return "", err
}
return f.Name(), nil
}
func containerPathSeparator(pattern string) bool {
for i := 0; i < len(pattern); i++ {
if os.IsPathSeparator(pattern[i]) {