mirror of
https://github.com/ahmetb/kubectx.git
synced 2025-06-24 14:32:24 +00:00
Implement switch via editing yaml in-place
Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
This commit is contained in:
parent
04e963c02c
commit
a9476f3215
@ -20,15 +20,25 @@ func main() {
|
||||
case ListOp:
|
||||
printListContexts(os.Stdout)
|
||||
case SwitchOp:
|
||||
// TODO implement
|
||||
panic("not implemented")
|
||||
if v.Target == "-" {
|
||||
// TODO implement swap
|
||||
panic("not implemented")
|
||||
}
|
||||
newCtx, err := switchContext(v.Target)
|
||||
if err != nil {
|
||||
printError("faield to switch context: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "Switched to context %q.\n", newCtx)
|
||||
case UnknownOp:
|
||||
fmt.Printf("%s unsupported operation: %s\n",
|
||||
color.RedString("error:"),
|
||||
strings.Join(v.Args, " "))
|
||||
printError("unsupported operation: %s", strings.Join(v.Args, " "))
|
||||
printHelp(os.Stdout)
|
||||
os.Exit(1)
|
||||
default:
|
||||
fmt.Printf("internal error: operation type %T not handled", op)
|
||||
}
|
||||
}
|
||||
|
||||
func printError(format string, args ...interface{}) {
|
||||
fmt.Fprintf(os.Stderr, color.RedString("error: "+format+"\n"), args...)
|
||||
}
|
||||
|
103
cmd/kubectx/switch.go
Normal file
103
cmd/kubectx/switch.go
Normal file
@ -0,0 +1,103 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// switchContext switches to specified context name.
|
||||
func switchContext(name string) (string, error) {
|
||||
cfgPath, err := kubeconfigPath()
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "cannot determine kubeconfig path")
|
||||
}
|
||||
f, err := os.OpenFile(cfgPath, os.O_RDWR, 0)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "failed to open file")
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
kc, err := parseKubeconfigRaw(f)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "yaml parse error")
|
||||
}
|
||||
|
||||
cur := getCurrentContext(kc)
|
||||
fmt.Printf("current-context=%s\n", cur)
|
||||
|
||||
if err := modifyCurrentContext(kc, name); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err := f.Truncate(0); err != nil {
|
||||
return "", errors.Wrap(err, "failed to truncate")
|
||||
}
|
||||
|
||||
if _, err := f.Seek(0, 0); err != nil {
|
||||
return "", errors.Wrap(err, "failed to seek")
|
||||
}
|
||||
|
||||
if err := saveKubeconfigRaw(f, kc); err != nil {
|
||||
return "", errors.Wrap(err, "failed to save kubeconfig")
|
||||
}
|
||||
return name, nil
|
||||
}
|
||||
|
||||
|
||||
// getCurrentContext returns "current-context" value in given
|
||||
// kubeconfig object Node, or returns "" if not found.
|
||||
func getCurrentContext(rootNode *yaml.Node) string {
|
||||
if rootNode.Kind != yaml.MappingNode {
|
||||
return ""
|
||||
}
|
||||
for i, ch := range rootNode.Content {
|
||||
if i%2 == 0 && ch.Value == "current-context" {
|
||||
return rootNode.Content[i+1].Value
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func modifyCurrentContext(rootNode *yaml.Node, name string) error {
|
||||
if rootNode.Kind != yaml.MappingNode {
|
||||
return errors.New("document is not a map")
|
||||
}
|
||||
|
||||
// find current-context field => modify value (next children)
|
||||
for i, ch := range rootNode.Content {
|
||||
if i%2 == 0 && ch.Value == "current-context" {
|
||||
rootNode.Content[i+1].Value = name
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// if current-context ==> create new field
|
||||
keyNode := &yaml.Node{
|
||||
Kind: yaml.ScalarNode,
|
||||
Value: "current-context",
|
||||
Tag: "!!str"}
|
||||
valueNode := &yaml.Node{
|
||||
Kind: yaml.ScalarNode,
|
||||
Value: name,
|
||||
Tag: "!!str"}
|
||||
rootNode.Content = append(rootNode.Content, keyNode, valueNode)
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseKubeconfigRaw(r io.Reader) (*yaml.Node, error) {
|
||||
var v yaml.Node
|
||||
if err := yaml.NewDecoder(r).Decode(&v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return v.Content[0], nil
|
||||
}
|
||||
|
||||
func saveKubeconfigRaw(w io.Writer, rootNode *yaml.Node) error {
|
||||
enc := yaml.NewEncoder(w)
|
||||
enc.SetIndent(2)
|
||||
return enc.Encode(rootNode)
|
||||
}
|
Loading…
Reference in New Issue
Block a user