k9s/internal/xray/container_test.go

247 lines
5.7 KiB
Go

package xray_test
import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"testing"
"github.com/derailed/k9s/internal"
"github.com/derailed/k9s/internal/client"
"github.com/derailed/k9s/internal/dao"
"github.com/derailed/k9s/internal/render"
"github.com/derailed/k9s/internal/watch"
"github.com/derailed/k9s/internal/xray"
"github.com/rs/zerolog"
"github.com/stretchr/testify/assert"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/informers"
)
func init() {
zerolog.SetGlobalLevel(zerolog.FatalLevel)
}
func TestCOConfigMapRefs(t *testing.T) {
var re xray.Container
root := xray.NewTreeNode("root", "root")
ctx := context.WithValue(context.Background(), xray.KeyParent, root)
ctx = context.WithValue(ctx, internal.KeyFactory, makeFactory())
assert.Nil(t, re.Render(ctx, "", render.ContainerRes{Container: makeCMContainer("c1", false)}))
assert.Equal(t, xray.MissingRefStatus, root.Children[0].Children[0].Extras[xray.StatusKey])
}
func TestCORefs(t *testing.T) {
uu := map[string]struct {
co render.ContainerRes
level1, level2 int
e string
}{
"cm_required": {
co: render.ContainerRes{Container: makeCMContainer("c1", false)},
level1: 1,
level2: 1,
e: xray.MissingRefStatus,
},
"cm_optional": {
co: render.ContainerRes{Container: makeCMContainer("c1", true)},
level1: 1,
level2: 1,
e: xray.OkStatus,
},
"cm_doubleRef": {
co: render.ContainerRes{Container: makeDoubleCMKeysContainer("c1", false)},
level1: 1,
level2: 1,
e: xray.MissingRefStatus,
},
"sec_required": {
co: render.ContainerRes{Container: makeSecContainer("c1", false)},
level1: 1,
level2: 1,
e: xray.MissingRefStatus,
},
"sec_optional": {
co: render.ContainerRes{Container: makeSecContainer("c1", true)},
level1: 1,
level2: 1,
e: xray.OkStatus,
},
"envFrom_optional": {
co: render.ContainerRes{Container: makeCMEnvFromContainer("c1", false)},
level1: 1,
level2: 2,
e: xray.MissingRefStatus,
},
}
for k := range uu {
u := uu[k]
t.Run(k, func(t *testing.T) {
var re xray.Container
root := xray.NewTreeNode("root", "root")
ctx := context.WithValue(context.Background(), xray.KeyParent, root)
ctx = context.WithValue(ctx, internal.KeyFactory, makeFactory())
assert.Nil(t, re.Render(ctx, "", u.co))
assert.Equal(t, u.level1, root.CountChildren())
assert.Equal(t, u.level2, root.Children[0].CountChildren())
assert.Equal(t, u.e, root.Children[0].Children[0].Extras[xray.StatusKey])
})
}
}
// ----------------------------------------------------------------------------
// Helpers...
func makeFactory() testFactory {
return testFactory{}
}
type testFactory struct {
rows map[string][]runtime.Object
}
var _ dao.Factory = testFactory{}
func (f testFactory) Client() client.Connection {
return nil
}
func (f testFactory) Get(gvr, path string, wait bool, sel labels.Selector) (runtime.Object, error) {
oo, ok := f.rows[gvr]
if ok && len(oo) > 0 {
return oo[0], nil
}
return nil, nil
}
func (f testFactory) List(gvr, ns string, wait bool, sel labels.Selector) ([]runtime.Object, error) {
oo, ok := f.rows[gvr]
if ok {
return oo, nil
}
return nil, nil
}
func (f testFactory) ForResource(ns, gvr string) informers.GenericInformer {
return nil
}
func (f testFactory) CanForResource(ns, gvr string, verbs []string) (informers.GenericInformer, error) {
return nil, nil
}
func (f testFactory) WaitForCacheSync() {}
func (f testFactory) Forwarders() watch.Forwarders {
return nil
}
func (f testFactory) DeleteForwarder(string) {}
func makeCMEnvFromContainer(n string, optional bool) *v1.Container {
return &v1.Container{
Name: n,
EnvFrom: []v1.EnvFromSource{
{
ConfigMapRef: &v1.ConfigMapEnvSource{
LocalObjectReference: v1.LocalObjectReference{
Name: "cm1",
},
Optional: &optional,
},
SecretRef: &v1.SecretEnvSource{
LocalObjectReference: v1.LocalObjectReference{
Name: "sec1",
},
Optional: &optional,
},
},
},
}
}
func makeCMContainer(n string, optional bool) *v1.Container {
return &v1.Container{
Name: n,
Env: []v1.EnvVar{
{
Name: "e1",
ValueFrom: &v1.EnvVarSource{
ConfigMapKeyRef: &v1.ConfigMapKeySelector{
LocalObjectReference: v1.LocalObjectReference{
Name: "cm1",
},
Key: "k1",
Optional: &optional,
},
},
},
},
}
}
func makeSecContainer(n string, optional bool) *v1.Container {
return &v1.Container{
Name: n,
Env: []v1.EnvVar{
{
Name: "e1",
ValueFrom: &v1.EnvVarSource{
SecretKeyRef: &v1.SecretKeySelector{
LocalObjectReference: v1.LocalObjectReference{
Name: "sec1",
},
Key: "k1",
Optional: &optional,
},
},
},
},
}
}
func makeDoubleCMKeysContainer(n string, optional bool) *v1.Container {
return &v1.Container{
Name: n,
Env: []v1.EnvVar{
{
Name: "e1",
ValueFrom: &v1.EnvVarSource{
ConfigMapKeyRef: &v1.ConfigMapKeySelector{
LocalObjectReference: v1.LocalObjectReference{
Name: "cm1",
},
Key: "k2",
Optional: &optional,
},
},
},
{
Name: "e2",
ValueFrom: &v1.EnvVarSource{
ConfigMapKeyRef: &v1.ConfigMapKeySelector{
LocalObjectReference: v1.LocalObjectReference{
Name: "cm1",
},
Key: "k1",
Optional: &optional,
},
},
},
},
}
}
func load(t *testing.T, n string) *unstructured.Unstructured {
raw, err := ioutil.ReadFile(fmt.Sprintf("testdata/%s.json", n))
assert.Nil(t, err)
var o unstructured.Unstructured
err = json.Unmarshal(raw, &o)
assert.Nil(t, err)
return &o
}