mirror of
https://github.com/ahmetb/kubectx.git
synced 2025-06-24 06:27:33 +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 {
|
func (_op CurrentOp) Run(stdout, _ io.Writer) error {
|
||||||
kc := new(kubeconfig.Kubeconfig).WithLoader(defaultLoader)
|
kc := new(kubeconfig.Kubeconfig).WithLoader(defaultLoader)
|
||||||
defer kc.Close()
|
defer kc.Close()
|
||||||
rootNode, err := kc.ParseRaw()
|
_, err := kc.ParseRaw()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
v := kubeconfig.GetCurrentContext(rootNode)
|
v := kc.GetCurrentContext()
|
||||||
if v == "" {
|
if v == "" {
|
||||||
return errors.New("current-context is not set")
|
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
|
return "", false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cur := kubeconfig.GetCurrentContext(rootNode)
|
cur := kc.GetCurrentContext()
|
||||||
|
|
||||||
// resolve "." to a real name
|
// resolve "." to a real name
|
||||||
if name == "." {
|
if name == "." {
|
||||||
@ -50,7 +50,7 @@ func deleteContext(name string) (deleteName string, wasActiveContext bool, err e
|
|||||||
name = cur
|
name = cur
|
||||||
}
|
}
|
||||||
|
|
||||||
if !checkContextExists(rootNode, name) {
|
if !kc.ContextExists(name) {
|
||||||
return "", false, errors.New("context does not exist")
|
return "", false, errors.New("context does not exist")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
package kubeconfig
|
package kubeconfig
|
||||||
|
|
||||||
import "gopkg.in/yaml.v3"
|
import (
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
)
|
||||||
|
|
||||||
func ContextNames(rootNode *yaml.Node) []string {
|
func (k *Kubeconfig) ContextNames() []string {
|
||||||
contexts := valueOf(rootNode, "contexts")
|
contexts := valueOf(k.rootNode, "contexts")
|
||||||
if contexts == nil {
|
if contexts == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -21,17 +23,14 @@ func ContextNames(rootNode *yaml.Node) []string {
|
|||||||
return ctxNames
|
return ctxNames
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCurrentContext returns "current-context" value in given
|
func (k *Kubeconfig) ContextExists(name string) bool {
|
||||||
// kubeconfig object Node, or returns "" if not found.
|
ctxNames := k.ContextNames()
|
||||||
func GetCurrentContext(rootNode *yaml.Node) string {
|
for _, v := range ctxNames {
|
||||||
if rootNode.Kind != yaml.MappingNode {
|
if v == name {
|
||||||
return ""
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
v := valueOf(rootNode, "current-context")
|
return false
|
||||||
if v == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return v.Value
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func valueOf(mapNode *yaml.Node, key string) *yaml.Node {
|
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 {
|
func (_ ListOp) Run(stdout, _ io.Writer) error {
|
||||||
kc := new(kubeconfig.Kubeconfig).WithLoader(defaultLoader)
|
kc := new(kubeconfig.Kubeconfig).WithLoader(defaultLoader)
|
||||||
defer kc.Close()
|
defer kc.Close()
|
||||||
rootNode, err := kc.ParseRaw()
|
_, err := kc.ParseRaw()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
ctxs := kubeconfig.ContextNames(rootNode)
|
ctxs := kc.ContextNames()
|
||||||
natsort.Sort(ctxs)
|
natsort.Sort(ctxs)
|
||||||
|
|
||||||
// TODO support KUBECTX_CURRENT_FGCOLOR
|
// TODO support KUBECTX_CURRENT_FGCOLOR
|
||||||
// TODO support KUBECTX_CURRENT_BGCOLOR
|
// TODO support KUBECTX_CURRENT_BGCOLOR
|
||||||
cur := kubeconfig.GetCurrentContext(rootNode)
|
cur := kc.GetCurrentContext()
|
||||||
for _, c := range ctxs {
|
for _, c := range ctxs {
|
||||||
s := c
|
s := c
|
||||||
if c == cur {
|
if c == cur {
|
||||||
|
@ -42,16 +42,16 @@ func (op RenameOp) Run(_, stderr io.Writer) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
cur := kubeconfig.GetCurrentContext(rootNode)
|
cur := kc.GetCurrentContext()
|
||||||
if op.Old == "." {
|
if op.Old == "." {
|
||||||
op.Old = cur
|
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)
|
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)
|
printWarning(stderr, "context %q exists, overwriting it.", op.New)
|
||||||
if err := modifyDocToDeleteContext(rootNode, op.New); err != nil {
|
if err := modifyDocToDeleteContext(rootNode, op.New); err != nil {
|
||||||
return errors.Wrap(err, "failed to delete new context to overwrite it")
|
return errors.Wrap(err, "failed to delete new context to overwrite it")
|
||||||
|
@ -44,8 +44,8 @@ func switchContext(name string) (string, error) {
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
prev := kubeconfig.GetCurrentContext(rootNode)
|
prev := kc.GetCurrentContext()
|
||||||
if !checkContextExists(rootNode, name) {
|
if !kc.ContextExists(name) {
|
||||||
return "", errors.Errorf("no context exists with the name: %q", name)
|
return "", errors.Errorf("no context exists with the name: %q", name)
|
||||||
}
|
}
|
||||||
if err := modifyCurrentContext(rootNode, name); err != nil {
|
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
|
// TODO delete
|
||||||
func valueOf(mapNode *yaml.Node, key string) *yaml.Node {
|
func valueOf(mapNode *yaml.Node, key string) *yaml.Node {
|
||||||
if mapNode.Kind != yaml.MappingNode {
|
if mapNode.Kind != yaml.MappingNode {
|
||||||
|
@ -5,7 +5,6 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"gopkg.in/yaml.v3"
|
|
||||||
|
|
||||||
"github.com/ahmetb/kubectx/cmd/kubectx/kubeconfig"
|
"github.com/ahmetb/kubectx/cmd/kubectx/kubeconfig"
|
||||||
)
|
)
|
||||||
@ -17,12 +16,12 @@ func (_ UnsetOp) Run(_, stderr io.Writer) error {
|
|||||||
kc := new(kubeconfig.Kubeconfig).WithLoader(defaultLoader)
|
kc := new(kubeconfig.Kubeconfig).WithLoader(defaultLoader)
|
||||||
defer kc.Close()
|
defer kc.Close()
|
||||||
|
|
||||||
rootNode, err := kc.ParseRaw()
|
_, err := kc.ParseRaw()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := modifyDocToUnsetContext(rootNode); err != nil {
|
if err := kc.UnsetCurrentContext(); err != nil {
|
||||||
return errors.Wrap(err, "error while modifying current-context")
|
return errors.Wrap(err, "error while modifying current-context")
|
||||||
}
|
}
|
||||||
if err := kc.Save(); err != nil {
|
if err := kc.Save(); err != nil {
|
||||||
@ -33,11 +32,3 @@ func (_ UnsetOp) Run(_, stderr io.Writer) error {
|
|||||||
return err
|
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