mirror of
https://github.com/ahmetb/kubectx.git
synced 2025-06-23 05:59:00 +00:00
Move ctx-related YAML parse methods to pkg
Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
This commit is contained in:
parent
7013899503
commit
492e3e7053
@ -15,12 +15,12 @@ type CurrentOp struct{}
|
||||
func (_op CurrentOp) Run(stdout, _ io.Writer) error {
|
||||
kc := new(kubeconfig.Kubeconfig).WithLoader(defaultLoader)
|
||||
defer kc.Close()
|
||||
rootNode, err := kc.ParseRaw()
|
||||
_, err := kc.ParseRaw()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
v := kubeconfig.GetCurrentContext(rootNode)
|
||||
v := kc.GetCurrentContext()
|
||||
if v == "" {
|
||||
return errors.New("current-context is not set")
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ func deleteContext(name string) (deleteName string, wasActiveContext bool, err e
|
||||
return "", false, err
|
||||
}
|
||||
|
||||
cur := kubeconfig.GetCurrentContext(rootNode)
|
||||
cur := kc.GetCurrentContext()
|
||||
|
||||
// resolve "." to a real name
|
||||
if name == "." {
|
||||
@ -50,7 +50,7 @@ func deleteContext(name string) (deleteName string, wasActiveContext bool, err e
|
||||
name = cur
|
||||
}
|
||||
|
||||
if !checkContextExists(rootNode, name) {
|
||||
if !kc.ContextExists(name) {
|
||||
return "", false, errors.New("context does not exist")
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,11 @@
|
||||
package kubeconfig
|
||||
|
||||
import "gopkg.in/yaml.v3"
|
||||
import (
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func ContextNames(rootNode *yaml.Node) []string {
|
||||
contexts := valueOf(rootNode, "contexts")
|
||||
func (k *Kubeconfig) ContextNames() []string {
|
||||
contexts := valueOf(k.rootNode, "contexts")
|
||||
if contexts == nil {
|
||||
return nil
|
||||
}
|
||||
@ -21,17 +23,14 @@ func ContextNames(rootNode *yaml.Node) []string {
|
||||
return ctxNames
|
||||
}
|
||||
|
||||
// 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 ""
|
||||
func (k *Kubeconfig) ContextExists(name string) bool {
|
||||
ctxNames := k.ContextNames()
|
||||
for _, v := range ctxNames {
|
||||
if v == name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
v := valueOf(rootNode, "current-context")
|
||||
if v == nil {
|
||||
return ""
|
||||
}
|
||||
return v.Value
|
||||
return false
|
||||
}
|
||||
|
||||
func valueOf(mapNode *yaml.Node, key string) *yaml.Node {
|
52
cmd/kubectx/kubeconfig/contexts_test.go
Normal file
52
cmd/kubectx/kubeconfig/contexts_test.go
Normal file
@ -0,0 +1,52 @@
|
||||
package kubeconfig
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
)
|
||||
|
||||
func TestKubeconfig_ContextNames(t *testing.T) {
|
||||
tl := &testLoader{in: strings.NewReader(`
|
||||
contexts:
|
||||
- name: abc
|
||||
- name: def
|
||||
field1: value1
|
||||
- name: ghi
|
||||
foo:
|
||||
bar: zoo`)}
|
||||
|
||||
kc := new(Kubeconfig).WithLoader(tl)
|
||||
_, err := kc.ParseRaw()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ctx := kc.ContextNames()
|
||||
expected := []string{"abc", "def", "ghi"}
|
||||
if diff := cmp.Diff(expected, ctx); diff != "" {
|
||||
t.Fatalf("%s", diff)
|
||||
}
|
||||
}
|
||||
|
||||
func TestKubeconfig_CheckContextExists(t *testing.T) {
|
||||
tl := &testLoader{in: strings.NewReader(`contexts:
|
||||
- name: c1
|
||||
- name: c2`)}
|
||||
|
||||
kc := new(Kubeconfig).WithLoader(tl)
|
||||
_, err := kc.ParseRaw()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !kc.ContextExists("c1") {
|
||||
t.Fatal("c1 actually exists; reported false")
|
||||
}
|
||||
if !kc.ContextExists("c2") {
|
||||
t.Fatal("c2 actually exists; reported false")
|
||||
}
|
||||
if kc.ContextExists("c3") {
|
||||
t.Fatal("c3 does not exist; but reported true")
|
||||
}
|
||||
}
|
28
cmd/kubectx/kubeconfig/currentcontext.go
Normal file
28
cmd/kubectx/kubeconfig/currentcontext.go
Normal file
@ -0,0 +1,28 @@
|
||||
package kubeconfig
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// GetCurrentContext returns "current-context" value in given
|
||||
// kubeconfig object Node, or returns "" if not found.
|
||||
func (k *Kubeconfig) GetCurrentContext() string {
|
||||
if k.rootNode.Kind != yaml.MappingNode {
|
||||
return ""
|
||||
}
|
||||
v := valueOf(k.rootNode, "current-context")
|
||||
if v == nil {
|
||||
return ""
|
||||
}
|
||||
return v.Value
|
||||
}
|
||||
|
||||
func (k *Kubeconfig) UnsetCurrentContext() error {
|
||||
if k.rootNode.Kind != yaml.MappingNode {
|
||||
return errors.New("kubeconfig file is not a map document")
|
||||
}
|
||||
curCtxValNode := valueOf(k.rootNode, "current-context")
|
||||
curCtxValNode.Value = ""
|
||||
return nil
|
||||
}
|
58
cmd/kubectx/kubeconfig/currentcontext_test.go
Normal file
58
cmd/kubectx/kubeconfig/currentcontext_test.go
Normal file
@ -0,0 +1,58 @@
|
||||
package kubeconfig
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestKubeconfig_GetCurrentContext(t *testing.T) {
|
||||
tl := &testLoader{in: strings.NewReader(`current-context: foo`)}
|
||||
kc := new(Kubeconfig).WithLoader(tl)
|
||||
_, err := kc.ParseRaw()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
v := kc.GetCurrentContext()
|
||||
|
||||
expected := "foo"
|
||||
if v != expected {
|
||||
t.Fatalf("expected=%q; got=%q", expected, v)
|
||||
}
|
||||
}
|
||||
|
||||
func TestKubeconfig_GetCurrentContext_missingField(t *testing.T) {
|
||||
tl := &testLoader{in: strings.NewReader(`abc: def`)}
|
||||
kc := new(Kubeconfig).WithLoader(tl)
|
||||
_, err := kc.ParseRaw()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
v := kc.GetCurrentContext()
|
||||
|
||||
expected := ""
|
||||
if v != expected {
|
||||
t.Fatalf("expected=%q; got=%q", expected, v)
|
||||
}
|
||||
}
|
||||
|
||||
func TestKubeconfig_UnsetCurrentContext(t *testing.T) {
|
||||
tl := &testLoader{in: strings.NewReader(`current-context: foo`)}
|
||||
kc := new(Kubeconfig).WithLoader(tl)
|
||||
_, err := kc.ParseRaw()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := kc.UnsetCurrentContext(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := kc.Save(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
out := tl.out.String()
|
||||
expected := `current-context: ""
|
||||
`
|
||||
if out != expected {
|
||||
t.Fatalf("expected=%q; got=%q", expected, out)
|
||||
}
|
||||
}
|
17
cmd/kubectx/kubeconfig/helpers_test.go
Normal file
17
cmd/kubectx/kubeconfig/helpers_test.go
Normal file
@ -0,0 +1,17 @@
|
||||
package kubeconfig
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type testLoader struct {
|
||||
in *strings.Reader
|
||||
out bytes.Buffer
|
||||
}
|
||||
|
||||
func (t *testLoader) Read(p []byte) (n int, err error) { return t.in.Read(p) }
|
||||
func (t *testLoader) Write(p []byte) (n int, err error) { return t.out.Write(p) }
|
||||
func (t *testLoader) Close() error { return nil }
|
||||
func (t *testLoader) Reset() error { return nil }
|
||||
func (t *testLoader) Load() (ReadWriteResetCloser, error) { return t, nil }
|
@ -26,17 +26,17 @@ type ListOp struct{}
|
||||
func (_ ListOp) Run(stdout, _ io.Writer) error {
|
||||
kc := new(kubeconfig.Kubeconfig).WithLoader(defaultLoader)
|
||||
defer kc.Close()
|
||||
rootNode, err := kc.ParseRaw()
|
||||
_, err := kc.ParseRaw()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctxs := kubeconfig.ContextNames(rootNode)
|
||||
ctxs := kc.ContextNames()
|
||||
natsort.Sort(ctxs)
|
||||
|
||||
// TODO support KUBECTX_CURRENT_FGCOLOR
|
||||
// TODO support KUBECTX_CURRENT_BGCOLOR
|
||||
cur := kubeconfig.GetCurrentContext(rootNode)
|
||||
cur := kc.GetCurrentContext()
|
||||
for _, c := range ctxs {
|
||||
s := c
|
||||
if c == cur {
|
||||
|
@ -42,16 +42,16 @@ func (op RenameOp) Run(_, stderr io.Writer) error {
|
||||
return err
|
||||
}
|
||||
|
||||
cur := kubeconfig.GetCurrentContext(rootNode)
|
||||
cur := kc.GetCurrentContext()
|
||||
if op.Old == "." {
|
||||
op.Old = cur
|
||||
}
|
||||
|
||||
if !checkContextExists(rootNode, op.Old) {
|
||||
if !kc.ContextExists(op.Old) {
|
||||
return errors.Errorf("context %q not found, can't rename it", op.Old)
|
||||
}
|
||||
|
||||
if checkContextExists(rootNode, op.New) {
|
||||
if kc.ContextExists( op.New) {
|
||||
printWarning(stderr, "context %q exists, overwriting it.", op.New)
|
||||
if err := modifyDocToDeleteContext(rootNode, op.New); err != nil {
|
||||
return errors.Wrap(err, "failed to delete new context to overwrite it")
|
||||
|
@ -44,8 +44,8 @@ func switchContext(name string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
|
||||
prev := kubeconfig.GetCurrentContext(rootNode)
|
||||
if !checkContextExists(rootNode, name) {
|
||||
prev := kc.GetCurrentContext()
|
||||
if !kc.ContextExists(name) {
|
||||
return "", errors.Errorf("no context exists with the name: %q", name)
|
||||
}
|
||||
if err := modifyCurrentContext(rootNode, name); err != nil {
|
||||
@ -81,16 +81,6 @@ func swapContext() (string, error) {
|
||||
}
|
||||
|
||||
|
||||
func checkContextExists(rootNode *yaml.Node, name string) bool {
|
||||
ctxNames := kubeconfig.ContextNames(rootNode)
|
||||
for _, v := range ctxNames {
|
||||
if v == name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// TODO delete
|
||||
func valueOf(mapNode *yaml.Node, key string) *yaml.Node {
|
||||
if mapNode.Kind != yaml.MappingNode {
|
||||
|
@ -5,7 +5,6 @@ import (
|
||||
"io"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
"github.com/ahmetb/kubectx/cmd/kubectx/kubeconfig"
|
||||
)
|
||||
@ -17,12 +16,12 @@ func (_ UnsetOp) Run(_, stderr io.Writer) error {
|
||||
kc := new(kubeconfig.Kubeconfig).WithLoader(defaultLoader)
|
||||
defer kc.Close()
|
||||
|
||||
rootNode, err := kc.ParseRaw()
|
||||
_, err := kc.ParseRaw()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := modifyDocToUnsetContext(rootNode); err != nil {
|
||||
if err := kc.UnsetCurrentContext(); err != nil {
|
||||
return errors.Wrap(err, "error while modifying current-context")
|
||||
}
|
||||
if err := kc.Save(); err != nil {
|
||||
@ -33,11 +32,3 @@ func (_ UnsetOp) Run(_, stderr io.Writer) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func modifyDocToUnsetContext(rootNode *yaml.Node) error {
|
||||
if rootNode.Kind != yaml.MappingNode {
|
||||
return errors.New("kubeconfig file is not a map document")
|
||||
}
|
||||
curCtxValNode := valueOf(rootNode, "current-context")
|
||||
curCtxValNode.Value = ""
|
||||
return nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user