471 lines
12 KiB
Go
471 lines
12 KiB
Go
package xray_test
|
|
|
|
import (
|
|
"regexp"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/derailed/k9s/internal/xray"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestTreeNodeCount(t *testing.T) {
|
|
uu := map[string]struct {
|
|
root *xray.TreeNode
|
|
e int
|
|
}{
|
|
"simple": {
|
|
root: root1(),
|
|
e: 3,
|
|
},
|
|
"complex": {
|
|
root: root3(),
|
|
e: 26,
|
|
},
|
|
}
|
|
|
|
for k := range uu {
|
|
u := uu[k]
|
|
t.Run(k, func(t *testing.T) {
|
|
assert.Equal(t, u.e, u.root.Count(""))
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestTreeNodeFilter(t *testing.T) {
|
|
uu := map[string]struct {
|
|
q string
|
|
root, e *xray.TreeNode
|
|
}{
|
|
"filter_simple": {
|
|
root: root1(),
|
|
e: diff1(),
|
|
q: "c1",
|
|
},
|
|
"filter_complex": {
|
|
root: root2(),
|
|
e: diff2(),
|
|
q: "c2",
|
|
},
|
|
"filter_no_match": {
|
|
root: root2(),
|
|
e: nil,
|
|
q: "bozo",
|
|
},
|
|
"filter_all_match": {
|
|
root: root2(),
|
|
e: root2(),
|
|
q: "",
|
|
},
|
|
"filter_complex1": {
|
|
root: root3(),
|
|
e: diff3(),
|
|
q: "coredns",
|
|
},
|
|
}
|
|
|
|
rx := func(q, path string) bool {
|
|
rx := regexp.MustCompile(`(?i)` + q)
|
|
|
|
tokens := strings.Split(path, "::")
|
|
for _, t := range tokens {
|
|
if rx.MatchString(t) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
for k := range uu {
|
|
u := uu[k]
|
|
t.Run(k, func(t *testing.T) {
|
|
filtered := u.root.Filter(u.q, rx)
|
|
assert.Equal(t, u.e, filtered)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestTreeNodeHydrate(t *testing.T) {
|
|
threeOK := strings.Join([]string{"ok", "ok", "ok"}, xray.PathSeparator)
|
|
fiveOK := strings.Join([]string{"ok", "ok", "ok", "ok", "ok"}, xray.PathSeparator)
|
|
|
|
uu := map[string]struct {
|
|
spec []xray.NodeSpec
|
|
e *xray.TreeNode
|
|
}{
|
|
"flat_simple": {
|
|
spec: []xray.NodeSpec{
|
|
{
|
|
GVR: "containers::v1/pods",
|
|
Path: "c1::default/p1",
|
|
Status: threeOK,
|
|
},
|
|
{
|
|
GVR: "containers::v1/pods",
|
|
Path: "c2::default/p1",
|
|
Status: threeOK,
|
|
},
|
|
},
|
|
e: root1(),
|
|
},
|
|
"flat_complex": {
|
|
spec: []xray.NodeSpec{
|
|
{
|
|
GVR: "v1/secrets::containers::v1/pods",
|
|
Path: "s1::c1::default/p1",
|
|
Status: threeOK,
|
|
},
|
|
{
|
|
GVR: "v1/secrets::containers::v1/pods",
|
|
Path: "s2::c2::default/p1",
|
|
Status: threeOK,
|
|
},
|
|
},
|
|
e: root2(),
|
|
},
|
|
"complex1": {
|
|
spec: []xray.NodeSpec{
|
|
{
|
|
GVR: "v1/secrets::v1/pods::apps/v1/deployments::v1/namespaces::apps/v1/deployments",
|
|
Path: "default/default-token-rr22g::default/nginx-6b866d578b-c6tcn::default/nginx::-/default::deployments",
|
|
Status: fiveOK,
|
|
},
|
|
{
|
|
GVR: "v1/configmaps::v1/pods::apps/v1/deployments::v1/namespaces::apps/v1/deployments",
|
|
Path: "kube-system/coredns::kube-system/coredns-6955765f44-89q2p::kube-system/coredns::-/kube-system::deployments",
|
|
Status: fiveOK,
|
|
},
|
|
{
|
|
GVR: "v1/secrets::v1/pods::apps/v1/deployments::v1/namespaces::apps/v1/deployments",
|
|
Path: "kube-system/coredns-token-5cq9j::kube-system/coredns-6955765f44-89q2p::kube-system/coredns::-/kube-system::deployments",
|
|
Status: fiveOK,
|
|
},
|
|
{
|
|
GVR: "v1/configmaps::v1/pods::apps/v1/deployments::v1/namespaces::apps/v1/deployments",
|
|
Path: "kube-system/coredns::kube-system/coredns-6955765f44-r9j9t::kube-system/coredns::-/kube-system::deployments",
|
|
Status: fiveOK,
|
|
},
|
|
{
|
|
GVR: "v1/secrets::v1/pods::apps/v1/deployments::v1/namespaces::apps/v1/deployments",
|
|
Path: "kube-system/coredns-token-5cq9j::kube-system/coredns-6955765f44-r9j9t::kube-system/coredns::-/kube-system::deployments",
|
|
Status: fiveOK,
|
|
},
|
|
{
|
|
GVR: "v1/secrets::v1/pods::apps/v1/deployments::v1/namespaces::apps/v1/deployments",
|
|
Path: "kube-system/default-token-thzt8::kube-system/metrics-server-6754dbc9df-88bk4::kube-system/metrics-server::-/kube-system::deployments",
|
|
Status: fiveOK,
|
|
},
|
|
{
|
|
GVR: "v1/secrets::v1/pods::apps/v1/deployments::v1/namespaces::apps/v1/deployments",
|
|
Path: "kube-system/nginx-ingress-token-kff5q::kube-system/nginx-ingress-controller-6fc5bcc8c9-cwp55::kube-system/nginx-ingress-controller::-/kube-system::deployments",
|
|
Status: fiveOK,
|
|
},
|
|
{
|
|
GVR: "v1/secrets::v1/pods::apps/v1/deployments::v1/namespaces::apps/v1/deployments",
|
|
Path: "kubernetes-dashboard/kubernetes-dashboard-token-d6rt4::kubernetes-dashboard/dashboard-metrics-scraper-7b64584c5c-c7b56::kubernetes-dashboard/dashboard-metrics-scraper::-/kubernetes-dashboard::deployments",
|
|
Status: fiveOK,
|
|
},
|
|
{
|
|
GVR: "v1/secrets::v1/pods::apps/v1/deployments::v1/namespaces::apps/v1/deployments",
|
|
Path: "kubernetes-dashboard/kubernetes-dashboard-token-d6rt4::kubernetes-dashboard/kubernetes-dashboard-79d9cd965-b4c7d::kubernetes-dashboard/kubernetes-dashboard::-/kubernetes-dashboard::deployments",
|
|
Status: fiveOK,
|
|
},
|
|
},
|
|
e: root3(),
|
|
},
|
|
}
|
|
|
|
for k := range uu {
|
|
u := uu[k]
|
|
t.Run(k, func(t *testing.T) {
|
|
root := xray.Hydrate(u.spec)
|
|
assert.Equal(t, u.e.Flatten(), root.Flatten())
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestTreeNodeFlatten(t *testing.T) {
|
|
uu := map[string]struct {
|
|
root *xray.TreeNode
|
|
e []xray.NodeSpec
|
|
}{
|
|
"flat_simple": {
|
|
root: root1(),
|
|
e: []xray.NodeSpec{
|
|
{
|
|
GVR: "containers::v1/pods",
|
|
Path: "c1::default/p1",
|
|
Status: strings.Join([]string{"ok", "ok"}, xray.PathSeparator),
|
|
},
|
|
{
|
|
GVR: "containers::v1/pods",
|
|
Path: "c2::default/p1",
|
|
Status: strings.Join([]string{"ok", "ok"}, xray.PathSeparator),
|
|
},
|
|
},
|
|
},
|
|
"flat_complex": {
|
|
root: root2(),
|
|
e: []xray.NodeSpec{
|
|
{
|
|
GVR: "v1/secrets::containers::v1/pods",
|
|
Path: "s1::c1::default/p1",
|
|
Status: strings.Join([]string{"ok", "ok", "ok"}, xray.PathSeparator),
|
|
},
|
|
{
|
|
GVR: "v1/secrets::containers::v1/pods",
|
|
Path: "s2::c2::default/p1",
|
|
Status: strings.Join([]string{"ok", "ok", "ok"}, xray.PathSeparator),
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
for k := range uu {
|
|
u := uu[k]
|
|
t.Run(k, func(t *testing.T) {
|
|
flat := u.root.Flatten()
|
|
assert.Equal(t, u.e, flat)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestTreeNodeDiff(t *testing.T) {
|
|
uu := map[string]struct {
|
|
n1, n2 *xray.TreeNode
|
|
e bool
|
|
}{
|
|
"blank": {
|
|
n1: &xray.TreeNode{},
|
|
n2: &xray.TreeNode{},
|
|
},
|
|
"same": {
|
|
n1: xray.NewTreeNode("v1/pods", "default/p1"),
|
|
n2: xray.NewTreeNode("v1/pods", "default/p1"),
|
|
},
|
|
}
|
|
|
|
for k := range uu {
|
|
u := uu[k]
|
|
t.Run(k, func(t *testing.T) {
|
|
assert.Equal(t, u.e, u.n1.Diff(u.n2))
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestTreeNodeClone(t *testing.T) {
|
|
n := xray.NewTreeNode("v1/pods", "default/p1")
|
|
c1 := xray.NewTreeNode("containers", "c1")
|
|
n.Add(c1)
|
|
|
|
c := n.ShallowClone()
|
|
assert.Equal(t, n.GVR, c.GVR)
|
|
}
|
|
|
|
func TestTreeNodeRoot(t *testing.T) {
|
|
n := xray.NewTreeNode("v1/pods", "default/p1")
|
|
c1 := xray.NewTreeNode("containers", "c1")
|
|
c2 := xray.NewTreeNode("containers", "c2")
|
|
n.Add(c1)
|
|
n.Add(c2)
|
|
|
|
assert.Equal(t, 2, n.CountChildren())
|
|
assert.Equal(t, n, n.Root())
|
|
assert.True(t, n.IsRoot())
|
|
assert.False(t, n.IsLeaf())
|
|
assert.Equal(t, n, c1.Root())
|
|
assert.False(t, c1.IsRoot())
|
|
assert.Equal(t, n, c2.Root())
|
|
assert.True(t, c1.IsLeaf())
|
|
}
|
|
|
|
func TestTreeNodeLevel(t *testing.T) {
|
|
n := xray.NewTreeNode("v1/pods", "default/p1")
|
|
c1 := xray.NewTreeNode("containers", "c1")
|
|
c2 := xray.NewTreeNode("containers", "c2")
|
|
n.Add(c1)
|
|
n.Add(c2)
|
|
|
|
assert.Equal(t, 0, n.Level())
|
|
assert.Equal(t, 1, c1.Level())
|
|
assert.Equal(t, 1, c2.Level())
|
|
}
|
|
|
|
func TestTreeNodeMaxDepth(t *testing.T) {
|
|
n := xray.NewTreeNode("v1/pods", "default/p1")
|
|
c1 := xray.NewTreeNode("containers", "c1")
|
|
c2 := xray.NewTreeNode("containers", "c2")
|
|
n.Add(c1)
|
|
n.Add(c2)
|
|
|
|
assert.Equal(t, 1, n.MaxDepth(0))
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Helpers...
|
|
|
|
func root1() *xray.TreeNode {
|
|
n := xray.NewTreeNode("v1/pods", "default/p1")
|
|
c1 := xray.NewTreeNode("containers", "c1")
|
|
c2 := xray.NewTreeNode("containers", "c2")
|
|
n.Add(c1)
|
|
n.Add(c2)
|
|
|
|
return n
|
|
}
|
|
|
|
func diff1() *xray.TreeNode {
|
|
n := xray.NewTreeNode("v1/pods", "default/p1")
|
|
c1 := xray.NewTreeNode("containers", "c1")
|
|
n.Add(c1)
|
|
|
|
return n
|
|
}
|
|
|
|
func root2() *xray.TreeNode {
|
|
n := xray.NewTreeNode("v1/pods", "default/p1")
|
|
c1 := xray.NewTreeNode("containers", "c1")
|
|
c2 := xray.NewTreeNode("containers", "c2")
|
|
n.Add(c1)
|
|
n.Add(c2)
|
|
|
|
s1 := xray.NewTreeNode("v1/secrets", "s1")
|
|
c1.Add(s1)
|
|
|
|
s2 := xray.NewTreeNode("v1/secrets", "s2")
|
|
c2.Add(s2)
|
|
|
|
return n
|
|
}
|
|
|
|
func diff2() *xray.TreeNode {
|
|
n := xray.NewTreeNode("v1/pods", "default/p1")
|
|
c1 := xray.NewTreeNode("containers", "c2")
|
|
n.Add(c1)
|
|
|
|
s1 := xray.NewTreeNode("v1/secrets", "s2")
|
|
c1.Add(s1)
|
|
|
|
return n
|
|
}
|
|
|
|
func root3() *xray.TreeNode {
|
|
n := xray.NewTreeNode("apps/v1/deployments", "deployments")
|
|
|
|
ns1 := xray.NewTreeNode("v1/namespaces", "-/default")
|
|
n.Add(ns1)
|
|
{
|
|
d1 := xray.NewTreeNode("apps/v1/deployments", "default/nginx")
|
|
ns1.Add(d1)
|
|
{
|
|
p1 := xray.NewTreeNode("v1/pods", "default/nginx-6b866d578b-c6tcn")
|
|
d1.Add(p1)
|
|
{
|
|
s1 := xray.NewTreeNode("v1/secrets", "default/default-token-rr22g")
|
|
p1.Add(s1)
|
|
}
|
|
}
|
|
}
|
|
|
|
ns2 := xray.NewTreeNode("v1/namespaces", "-/kube-system")
|
|
n.Add(ns2)
|
|
{
|
|
d2 := xray.NewTreeNode("apps/v1/deployments", "kube-system/coredns")
|
|
ns2.Add(d2)
|
|
{
|
|
p2 := xray.NewTreeNode("v1/pods", "kube-system/coredns-6955765f44-89q2p")
|
|
d2.Add(p2)
|
|
{
|
|
c1 := xray.NewTreeNode("v1/configmaps", "kube-system/coredns")
|
|
p2.Add(c1)
|
|
s2 := xray.NewTreeNode("v1/secrets", "kube-system/coredns-token-5cq9j")
|
|
p2.Add(s2)
|
|
}
|
|
p3 := xray.NewTreeNode("v1/pods", "kube-system/coredns-6955765f44-r9j9t")
|
|
d2.Add(p3)
|
|
{
|
|
c2 := xray.NewTreeNode("v1/configmaps", "kube-system/coredns")
|
|
p3.Add(c2)
|
|
s3 := xray.NewTreeNode("v1/secrets", "kube-system/coredns-token-5cq9j")
|
|
p3.Add(s3)
|
|
}
|
|
}
|
|
d3 := xray.NewTreeNode("apps/v1/deployments", "kube-system/metrics-server")
|
|
ns2.Add(d3)
|
|
{
|
|
p3 := xray.NewTreeNode("v1/pods", "kube-system/metrics-server-6754dbc9df-88bk4")
|
|
d3.Add(p3)
|
|
{
|
|
s4 := xray.NewTreeNode("v1/secrets", "kube-system/default-token-thzt8")
|
|
p3.Add(s4)
|
|
}
|
|
}
|
|
d4 := xray.NewTreeNode("apps/v1/deployments", "kube-system/nginx-ingress-controller")
|
|
ns2.Add(d4)
|
|
{
|
|
p4 := xray.NewTreeNode("v1/pods", "kube-system/nginx-ingress-controller-6fc5bcc8c9-cwp55")
|
|
d4.Add(p4)
|
|
{
|
|
s5 := xray.NewTreeNode("v1/secrets", "kube-system/nginx-ingress-token-kff5q")
|
|
p4.Add(s5)
|
|
}
|
|
}
|
|
}
|
|
|
|
ns3 := xray.NewTreeNode("v1/namespaces", "-/kubernetes-dashboard")
|
|
n.Add(ns3)
|
|
{
|
|
d5 := xray.NewTreeNode("apps/v1/deployments", "kubernetes-dashboard/dashboard-metrics-scraper")
|
|
ns3.Add(d5)
|
|
{
|
|
p5 := xray.NewTreeNode("v1/pods", "kubernetes-dashboard/dashboard-metrics-scraper-7b64584c5c-c7b56")
|
|
d5.Add(p5)
|
|
{
|
|
s6 := xray.NewTreeNode("v1/secrets", "kubernetes-dashboard/kubernetes-dashboard-token-d6rt4")
|
|
p5.Add(s6)
|
|
}
|
|
}
|
|
d6 := xray.NewTreeNode("apps/v1/deployments", "kubernetes-dashboard/kubernetes-dashboard")
|
|
ns3.Add(d6)
|
|
{
|
|
p6 := xray.NewTreeNode("v1/pods", "kubernetes-dashboard/kubernetes-dashboard-79d9cd965-b4c7d")
|
|
d6.Add(p6)
|
|
{
|
|
s6 := xray.NewTreeNode("v1/secrets", "kubernetes-dashboard/kubernetes-dashboard-token-d6rt4")
|
|
p6.Add(s6)
|
|
}
|
|
}
|
|
}
|
|
|
|
return n
|
|
}
|
|
|
|
func diff3() *xray.TreeNode {
|
|
n := xray.NewTreeNode("apps/v1/deployments", "deployments")
|
|
ns2 := xray.NewTreeNode("v1/namespaces", "-/kube-system")
|
|
n.Add(ns2)
|
|
{
|
|
d2 := xray.NewTreeNode("apps/v1/deployments", "kube-system/coredns")
|
|
ns2.Add(d2)
|
|
{
|
|
p2 := xray.NewTreeNode("v1/pods", "kube-system/coredns-6955765f44-89q2p")
|
|
d2.Add(p2)
|
|
{
|
|
c1 := xray.NewTreeNode("v1/configmaps", "kube-system/coredns")
|
|
p2.Add(c1)
|
|
s2 := xray.NewTreeNode("v1/secrets", "kube-system/coredns-token-5cq9j")
|
|
p2.Add(s2)
|
|
}
|
|
p3 := xray.NewTreeNode("v1/pods", "kube-system/coredns-6955765f44-r9j9t")
|
|
d2.Add(p3)
|
|
{
|
|
c2 := xray.NewTreeNode("v1/configmaps", "kube-system/coredns")
|
|
p3.Add(c2)
|
|
s3 := xray.NewTreeNode("v1/secrets", "kube-system/coredns-token-5cq9j")
|
|
p3.Add(s3)
|
|
}
|
|
}
|
|
}
|
|
return n
|
|
}
|