mirror of
https://github.com/ahmetb/kubectx.git
synced 2025-09-03 01:24:24 +00:00
Unit tests
This commit is contained in:
@@ -62,10 +62,16 @@ func Test_parseArgs_new(t *testing.T) {
|
|||||||
want: UnsupportedOp{fmt.Errorf("'-d' needs arguments")}},
|
want: UnsupportedOp{fmt.Errorf("'-d' needs arguments")}},
|
||||||
{name: "delete - current context",
|
{name: "delete - current context",
|
||||||
args: []string{"-d", "."},
|
args: []string{"-d", "."},
|
||||||
want: DeleteOp{[]string{"."}}},
|
want: DeleteOp{[]string{"."}, false}},
|
||||||
{name: "delete - multiple contexts",
|
{name: "delete - multiple contexts",
|
||||||
args: []string{"-d", ".", "a", "b"},
|
args: []string{"-d", ".", "a", "b"},
|
||||||
want: DeleteOp{[]string{".", "a", "b"}}},
|
want: DeleteOp{[]string{".", "a", "b"}, false}},
|
||||||
|
{name: "delete cascading- current context",
|
||||||
|
args: []string{"-D", "."},
|
||||||
|
want: DeleteOp{[]string{"."}, true}},
|
||||||
|
{name: "delete cascading - multiple contexts",
|
||||||
|
args: []string{"-D", ".", "a", "b"},
|
||||||
|
want: DeleteOp{[]string{".", "a", "b"}, true}},
|
||||||
{name: "rename context",
|
{name: "rename context",
|
||||||
args: []string{"a=b"},
|
args: []string{"a=b"},
|
||||||
want: RenameOp{"a", "b"}},
|
want: RenameOp{"a", "b"}},
|
||||||
|
124
internal/kubeconfig/clusters_test.go
Normal file
124
internal/kubeconfig/clusters_test.go
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
package kubeconfig
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
|
|
||||||
|
"github.com/ahmetb/kubectx/internal/testutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestKubeconfig_ClusterOfContext_ctxNotFound(t *testing.T) {
|
||||||
|
kc := new(Kubeconfig).WithLoader(WithMockKubeconfigLoader(testutil.KC().
|
||||||
|
WithCtxs(testutil.Ctx("c1")).ToYAML(t)))
|
||||||
|
if err := kc.Parse(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := kc.ClusterOfContext("c2")
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected err")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestKubeconfig_ClusterOfContext(t *testing.T) {
|
||||||
|
kc := new(Kubeconfig).WithLoader(WithMockKubeconfigLoader(testutil.KC().
|
||||||
|
WithCtxs(
|
||||||
|
testutil.Ctx("c1").Cluster("c1c1"),
|
||||||
|
testutil.Ctx("c2").Cluster("c2c2")).ToYAML(t)))
|
||||||
|
if err := kc.Parse(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
v1, err := kc.ClusterOfContext("c1")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("unexpected err", err)
|
||||||
|
}
|
||||||
|
if expected := `c1c1`; v1 != expected {
|
||||||
|
t.Fatalf("c1: expected=\"%s\" got=\"%s\"", expected, v1)
|
||||||
|
}
|
||||||
|
|
||||||
|
v2, err := kc.ClusterOfContext("c2")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("unexpected err", err)
|
||||||
|
}
|
||||||
|
if expected := `c2c2`; v2 != expected {
|
||||||
|
t.Fatalf("c2: expected=\"%s\" got=\"%s\"", expected, v2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestKubeconfig_DeleteClusterEntry_errors(t *testing.T) {
|
||||||
|
kc := new(Kubeconfig).WithLoader(WithMockKubeconfigLoader(`[1, 2, 3]`))
|
||||||
|
_ = kc.Parse()
|
||||||
|
err := kc.DeleteClusterEntry("foo")
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("supposed to fail on non-mapping nodes")
|
||||||
|
}
|
||||||
|
|
||||||
|
kc = new(Kubeconfig).WithLoader(WithMockKubeconfigLoader(`a: b`))
|
||||||
|
_ = kc.Parse()
|
||||||
|
err = kc.DeleteClusterEntry("foo")
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("supposed to fail if clusters key does not exist")
|
||||||
|
}
|
||||||
|
|
||||||
|
kc = new(Kubeconfig).WithLoader(WithMockKubeconfigLoader(`clusters: "some string"`))
|
||||||
|
_ = kc.Parse()
|
||||||
|
err = kc.DeleteClusterEntry("foo")
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("supposed to fail if clusters key is not an array")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestKubeconfig_DeleteClusterEntry(t *testing.T) {
|
||||||
|
test := WithMockKubeconfigLoader(
|
||||||
|
testutil.KC().WithClusters(
|
||||||
|
testutil.Cluster("c1"),
|
||||||
|
testutil.Cluster("c2"),
|
||||||
|
testutil.Cluster("c3")).ToYAML(t))
|
||||||
|
kc := new(Kubeconfig).WithLoader(test)
|
||||||
|
if err := kc.Parse(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := kc.DeleteClusterEntry("c1"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := kc.Save(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
expected := testutil.KC().WithClusters(
|
||||||
|
testutil.Cluster("c2"),
|
||||||
|
testutil.Cluster("c3")).ToYAML(t)
|
||||||
|
out := test.Output()
|
||||||
|
if diff := cmp.Diff(expected, out); diff != "" {
|
||||||
|
t.Fatalf("diff: %s", diff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestKubeconfig_CountClusterReferences_errors(t *testing.T) {
|
||||||
|
kc := new(Kubeconfig).WithLoader(WithMockKubeconfigLoader(testutil.KC().
|
||||||
|
WithCtxs(
|
||||||
|
testutil.Ctx("c1").Cluster("c1c1"),
|
||||||
|
testutil.Ctx("c2").Cluster("c2c2"),
|
||||||
|
testutil.Ctx("c3").Cluster("c1c1")).ToYAML(t)))
|
||||||
|
if err := kc.Parse(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
count1, err := kc.CountClusterReferences("c1c1")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("unexpected err", err)
|
||||||
|
}
|
||||||
|
if expected := 2; count1 != expected {
|
||||||
|
t.Fatalf("c1: expected=\"%d\" got=\"%d\"", expected, count1)
|
||||||
|
}
|
||||||
|
|
||||||
|
count2, err := kc.CountClusterReferences("c2c2")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("unexpected err", err)
|
||||||
|
}
|
||||||
|
if expected := 1; count2 != expected {
|
||||||
|
t.Fatalf("c1: expected=\"%d\" got=\"%d\"", expected, count2)
|
||||||
|
}
|
||||||
|
}
|
124
internal/kubeconfig/users_test.go
Normal file
124
internal/kubeconfig/users_test.go
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
package kubeconfig
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
|
|
||||||
|
"github.com/ahmetb/kubectx/internal/testutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestKubeconfig_UserOfContext_ctxNotFound(t *testing.T) {
|
||||||
|
kc := new(Kubeconfig).WithLoader(WithMockKubeconfigLoader(testutil.KC().
|
||||||
|
WithCtxs(testutil.Ctx("c1")).ToYAML(t)))
|
||||||
|
if err := kc.Parse(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := kc.UserOfContext("c2")
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected err")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestKubeconfig_UserOfContext(t *testing.T) {
|
||||||
|
kc := new(Kubeconfig).WithLoader(WithMockKubeconfigLoader(testutil.KC().
|
||||||
|
WithCtxs(
|
||||||
|
testutil.Ctx("c1").User("c1u1"),
|
||||||
|
testutil.Ctx("c2").User("c2u2")).ToYAML(t)))
|
||||||
|
if err := kc.Parse(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
v1, err := kc.UserOfContext("c1")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("unexpected err", err)
|
||||||
|
}
|
||||||
|
if expected := `c1u1`; v1 != expected {
|
||||||
|
t.Fatalf("c1: expected=\"%s\" got=\"%s\"", expected, v1)
|
||||||
|
}
|
||||||
|
|
||||||
|
v2, err := kc.UserOfContext("c2")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("unexpected err", err)
|
||||||
|
}
|
||||||
|
if expected := `c2u2`; v2 != expected {
|
||||||
|
t.Fatalf("c2: expected=\"%s\" got=\"%s\"", expected, v2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestKubeconfig_DeleteUserEntry_errors(t *testing.T) {
|
||||||
|
kc := new(Kubeconfig).WithLoader(WithMockKubeconfigLoader(`[1, 2, 3]`))
|
||||||
|
_ = kc.Parse()
|
||||||
|
err := kc.DeleteUserEntry("foo")
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("supposed to fail on non-mapping nodes")
|
||||||
|
}
|
||||||
|
|
||||||
|
kc = new(Kubeconfig).WithLoader(WithMockKubeconfigLoader(`a: b`))
|
||||||
|
_ = kc.Parse()
|
||||||
|
err = kc.DeleteUserEntry("foo")
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("supposed to fail if users key does not exist")
|
||||||
|
}
|
||||||
|
|
||||||
|
kc = new(Kubeconfig).WithLoader(WithMockKubeconfigLoader(`users: "some string"`))
|
||||||
|
_ = kc.Parse()
|
||||||
|
err = kc.DeleteUserEntry("foo")
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("supposed to fail if users key is not an array")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestKubeconfig_DeleteUserEntry(t *testing.T) {
|
||||||
|
test := WithMockKubeconfigLoader(
|
||||||
|
testutil.KC().WithUsers(
|
||||||
|
testutil.User("u1"),
|
||||||
|
testutil.User("u2"),
|
||||||
|
testutil.User("u3")).ToYAML(t))
|
||||||
|
kc := new(Kubeconfig).WithLoader(test)
|
||||||
|
if err := kc.Parse(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := kc.DeleteUserEntry("u1"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := kc.Save(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
expected := testutil.KC().WithUsers(
|
||||||
|
testutil.User("u2"),
|
||||||
|
testutil.User("u3")).ToYAML(t)
|
||||||
|
out := test.Output()
|
||||||
|
if diff := cmp.Diff(expected, out); diff != "" {
|
||||||
|
t.Fatalf("diff: %s", diff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestKubeconfig_CountUserReferences_errors(t *testing.T) {
|
||||||
|
kc := new(Kubeconfig).WithLoader(WithMockKubeconfigLoader(testutil.KC().
|
||||||
|
WithCtxs(
|
||||||
|
testutil.Ctx("c1").User("c1u1"),
|
||||||
|
testutil.Ctx("c2").User("c2u2"),
|
||||||
|
testutil.Ctx("c3").User("c1u1")).ToYAML(t)))
|
||||||
|
if err := kc.Parse(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
count1, err := kc.CountUserReferences("c1u1")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("unexpected err", err)
|
||||||
|
}
|
||||||
|
if expected := 2; count1 != expected {
|
||||||
|
t.Fatalf("c1: expected=\"%d\" got=\"%d\"", expected, count1)
|
||||||
|
}
|
||||||
|
|
||||||
|
count2, err := kc.CountUserReferences("c2u2")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("unexpected err", err)
|
||||||
|
}
|
||||||
|
if expected := 1; count2 != expected {
|
||||||
|
t.Fatalf("c1: expected=\"%d\" got=\"%d\"", expected, count2)
|
||||||
|
}
|
||||||
|
}
|
@@ -21,15 +21,31 @@ import (
|
|||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Context struct {
|
type ContextObj struct {
|
||||||
Name string `yaml:"name,omitempty"`
|
Name string `yaml:"name,omitempty"`
|
||||||
Context struct {
|
Context struct {
|
||||||
Namespace string `yaml:"namespace,omitempty"`
|
Namespace string `yaml:"namespace,omitempty"`
|
||||||
|
User string `yaml:"user,omitempty"`
|
||||||
|
Cluster string `yaml:"cluster,omitempty"`
|
||||||
} `yaml:"context,omitempty"`
|
} `yaml:"context,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func Ctx(name string) *Context { return &Context{Name: name} }
|
func Ctx(name string) *ContextObj { return &ContextObj{Name: name} }
|
||||||
func (c *Context) Ns(ns string) *Context { c.Context.Namespace = ns; return c }
|
func (c *ContextObj) Ns(ns string) *ContextObj { c.Context.Namespace = ns; return c }
|
||||||
|
func (c *ContextObj) User(user string) *ContextObj { c.Context.User = user; return c }
|
||||||
|
func (c *ContextObj) Cluster(cluster string) *ContextObj { c.Context.Cluster = cluster; return c }
|
||||||
|
|
||||||
|
type UserObj struct {
|
||||||
|
Name string `yaml:"name,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func User(name string) *UserObj { return &UserObj{Name: name} }
|
||||||
|
|
||||||
|
type ClusterObj struct {
|
||||||
|
Name string `yaml:"name,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func Cluster(name string) *ClusterObj { return &ClusterObj{Name: name} }
|
||||||
|
|
||||||
type Kubeconfig map[string]interface{}
|
type Kubeconfig map[string]interface{}
|
||||||
|
|
||||||
@@ -41,7 +57,9 @@ func KC() *Kubeconfig {
|
|||||||
|
|
||||||
func (k *Kubeconfig) Set(key string, v interface{}) *Kubeconfig { (*k)[key] = v; return k }
|
func (k *Kubeconfig) Set(key string, v interface{}) *Kubeconfig { (*k)[key] = v; return k }
|
||||||
func (k *Kubeconfig) WithCurrentCtx(s string) *Kubeconfig { (*k)["current-context"] = s; return k }
|
func (k *Kubeconfig) WithCurrentCtx(s string) *Kubeconfig { (*k)["current-context"] = s; return k }
|
||||||
func (k *Kubeconfig) WithCtxs(c ...*Context) *Kubeconfig { (*k)["contexts"] = c; return k }
|
func (k *Kubeconfig) WithCtxs(c ...*ContextObj) *Kubeconfig { (*k)["contexts"] = c; return k }
|
||||||
|
func (k *Kubeconfig) WithUsers(u ...*UserObj) *Kubeconfig { (*k)["users"] = u; return k }
|
||||||
|
func (k *Kubeconfig) WithClusters(c ...*ClusterObj) *Kubeconfig { (*k)["clusters"] = c; return k }
|
||||||
|
|
||||||
func (k *Kubeconfig) ToYAML(t *testing.T) string {
|
func (k *Kubeconfig) ToYAML(t *testing.T) string {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
Reference in New Issue
Block a user