594 lines
12 KiB
Go
594 lines
12 KiB
Go
// SPDX-License-Identifier: Apache-2.0
|
|
// Copyright Authors of K9s
|
|
|
|
package config_test
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/adrg/xdg"
|
|
"github.com/derailed/k9s/internal/client"
|
|
"github.com/derailed/k9s/internal/config"
|
|
"github.com/derailed/k9s/internal/config/data"
|
|
"github.com/derailed/k9s/internal/config/mock"
|
|
m "github.com/petergtz/pegomock"
|
|
"github.com/rs/zerolog"
|
|
"github.com/stretchr/testify/assert"
|
|
"k8s.io/cli-runtime/pkg/genericclioptions"
|
|
)
|
|
|
|
func init() {
|
|
zerolog.SetGlobalLevel(zerolog.FatalLevel)
|
|
}
|
|
|
|
func TestConfigSave(t *testing.T) {
|
|
config.AppConfigFile = "/tmp/k9s-test/k9s.yaml"
|
|
sd := "/tmp/k9s-test/screen-dumps"
|
|
cl, ct := "cl-1", "ct-1-1"
|
|
_ = os.RemoveAll(("/tmp/k9s-test"))
|
|
|
|
uu := map[string]struct {
|
|
ct string
|
|
flags *genericclioptions.ConfigFlags
|
|
k9sFlags *config.Flags
|
|
}{
|
|
"happy": {
|
|
ct: "ct-1-1",
|
|
flags: &genericclioptions.ConfigFlags{
|
|
ClusterName: &cl,
|
|
Context: &ct,
|
|
},
|
|
k9sFlags: &config.Flags{
|
|
ScreenDumpDir: &sd,
|
|
},
|
|
},
|
|
}
|
|
|
|
for k := range uu {
|
|
xdg.Reload()
|
|
u := uu[k]
|
|
t.Run(k, func(t *testing.T) {
|
|
c := mock.NewMockConfig()
|
|
_, err := c.K9s.ActivateContext(u.ct)
|
|
assert.NoError(t, err)
|
|
if u.flags != nil {
|
|
c.K9s.Override(u.k9sFlags)
|
|
assert.NoError(t, c.Refine(u.flags, u.k9sFlags, client.NewConfig(u.flags)))
|
|
}
|
|
assert.NoError(t, c.Save(true))
|
|
bb, err := os.ReadFile(config.AppConfigFile)
|
|
assert.NoError(t, err)
|
|
ee, err := os.ReadFile("testdata/configs/default.yaml")
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, string(ee), string(bb))
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSetActiveView(t *testing.T) {
|
|
var (
|
|
cfgFile = "testdata/kubes/test.yaml"
|
|
view = "dp"
|
|
)
|
|
|
|
uu := map[string]struct {
|
|
ct string
|
|
flags *genericclioptions.ConfigFlags
|
|
k9sFlags *config.Flags
|
|
view string
|
|
e string
|
|
}{
|
|
"empty": {
|
|
view: data.DefaultView,
|
|
e: data.DefaultView,
|
|
},
|
|
"not-exists": {
|
|
ct: "fred",
|
|
view: data.DefaultView,
|
|
e: data.DefaultView,
|
|
},
|
|
"happy": {
|
|
ct: "ct-1-1",
|
|
view: "xray",
|
|
e: "xray",
|
|
},
|
|
"cli-override": {
|
|
flags: &genericclioptions.ConfigFlags{
|
|
KubeConfig: &cfgFile,
|
|
},
|
|
k9sFlags: &config.Flags{
|
|
Command: &view,
|
|
},
|
|
ct: "ct-1-1",
|
|
view: "xray",
|
|
e: "dp",
|
|
},
|
|
}
|
|
|
|
for k := range uu {
|
|
u := uu[k]
|
|
t.Run(k, func(t *testing.T) {
|
|
c := mock.NewMockConfig()
|
|
_, _ = c.K9s.ActivateContext(u.ct)
|
|
if u.flags != nil {
|
|
assert.NoError(t, c.Refine(u.flags, nil, client.NewConfig(u.flags)))
|
|
c.K9s.Override(u.k9sFlags)
|
|
}
|
|
c.SetActiveView(u.view)
|
|
assert.Equal(t, u.e, c.ActiveView())
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestActiveContextName(t *testing.T) {
|
|
var (
|
|
cfgFile = "testdata/kubes/test.yaml"
|
|
ct2 = "ct-1-2"
|
|
)
|
|
|
|
uu := map[string]struct {
|
|
flags *genericclioptions.ConfigFlags
|
|
k9sFlags *config.Flags
|
|
ct string
|
|
e string
|
|
}{
|
|
"empty": {},
|
|
"happy": {
|
|
ct: "ct-1-1",
|
|
e: "ct-1-1",
|
|
},
|
|
"cli-override": {
|
|
flags: &genericclioptions.ConfigFlags{
|
|
KubeConfig: &cfgFile,
|
|
Context: &ct2,
|
|
},
|
|
k9sFlags: &config.Flags{},
|
|
ct: "ct-1-1",
|
|
e: "ct-1-2",
|
|
},
|
|
}
|
|
|
|
for k := range uu {
|
|
u := uu[k]
|
|
t.Run(k, func(t *testing.T) {
|
|
c := mock.NewMockConfig()
|
|
_, _ = c.K9s.ActivateContext(u.ct)
|
|
if u.flags != nil {
|
|
assert.NoError(t, c.Refine(u.flags, nil, client.NewConfig(u.flags)))
|
|
c.K9s.Override(u.k9sFlags)
|
|
}
|
|
assert.Equal(t, u.e, c.ActiveContextName())
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestActiveView(t *testing.T) {
|
|
var (
|
|
cfgFile = "testdata/kubes/test.yaml"
|
|
view = "dp"
|
|
)
|
|
|
|
uu := map[string]struct {
|
|
ct string
|
|
flags *genericclioptions.ConfigFlags
|
|
k9sFlags *config.Flags
|
|
e string
|
|
}{
|
|
"empty": {
|
|
e: data.DefaultView,
|
|
},
|
|
"not-exists": {
|
|
ct: "fred",
|
|
e: data.DefaultView,
|
|
},
|
|
"happy": {
|
|
ct: "ct-1-1",
|
|
e: data.DefaultView,
|
|
},
|
|
"cli-override": {
|
|
flags: &genericclioptions.ConfigFlags{
|
|
KubeConfig: &cfgFile,
|
|
},
|
|
k9sFlags: &config.Flags{
|
|
Command: &view,
|
|
},
|
|
e: "dp",
|
|
},
|
|
}
|
|
|
|
for k := range uu {
|
|
u := uu[k]
|
|
t.Run(k, func(t *testing.T) {
|
|
c := mock.NewMockConfig()
|
|
_, _ = c.K9s.ActivateContext(u.ct)
|
|
if u.flags != nil {
|
|
assert.NoError(t, c.Refine(u.flags, nil, client.NewConfig(u.flags)))
|
|
c.K9s.Override(u.k9sFlags)
|
|
}
|
|
assert.Equal(t, u.e, c.ActiveView())
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestFavNamespaces(t *testing.T) {
|
|
uu := map[string]struct {
|
|
ct string
|
|
e []string
|
|
}{
|
|
"empty": {},
|
|
"not-exists": {
|
|
ct: "fred",
|
|
},
|
|
"happy": {
|
|
ct: "ct-1-1",
|
|
e: []string{client.DefaultNamespace},
|
|
},
|
|
}
|
|
|
|
for k := range uu {
|
|
u := uu[k]
|
|
t.Run(k, func(t *testing.T) {
|
|
c := mock.NewMockConfig()
|
|
_, _ = c.K9s.ActivateContext(u.ct)
|
|
assert.Equal(t, u.e, c.FavNamespaces())
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestContextAliasesPath(t *testing.T) {
|
|
uu := map[string]struct {
|
|
ct string
|
|
e string
|
|
}{
|
|
"empty": {},
|
|
"not-exists": {
|
|
ct: "fred",
|
|
},
|
|
"happy": {
|
|
ct: "ct-1-1",
|
|
e: "/tmp/test/cl-1/ct-1-1/aliases.yaml",
|
|
},
|
|
}
|
|
|
|
for k := range uu {
|
|
u := uu[k]
|
|
t.Run(k, func(t *testing.T) {
|
|
c := mock.NewMockConfig()
|
|
_, _ = c.K9s.ActivateContext(u.ct)
|
|
assert.Equal(t, u.e, c.ContextAliasesPath())
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestContextPluginsPath(t *testing.T) {
|
|
uu := map[string]struct {
|
|
ct, e string
|
|
err error
|
|
}{
|
|
"empty": {
|
|
err: errors.New(`no context found for: ""`),
|
|
},
|
|
"happy": {
|
|
ct: "ct-1-1",
|
|
e: "/tmp/test/cl-1/ct-1-1/plugins.yaml",
|
|
},
|
|
"not-exists": {
|
|
ct: "fred",
|
|
err: errors.New(`no context found for: "fred"`),
|
|
},
|
|
}
|
|
|
|
for k := range uu {
|
|
u := uu[k]
|
|
t.Run(k, func(t *testing.T) {
|
|
c := mock.NewMockConfig()
|
|
_, _ = c.K9s.ActivateContext(u.ct)
|
|
s, err := c.ContextPluginsPath()
|
|
if err != nil {
|
|
assert.Equal(t, u.err, err)
|
|
}
|
|
assert.Equal(t, u.e, s)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestConfigLoader(t *testing.T) {
|
|
uu := map[string]struct {
|
|
f string
|
|
err string
|
|
}{
|
|
"happy": {
|
|
f: "testdata/configs/k9s.yaml",
|
|
},
|
|
"toast": {
|
|
f: "testdata/configs/k9s_toast.yaml",
|
|
err: `k9s config file "testdata/configs/k9s_toast.yaml" load failed:
|
|
Additional property disablePodCounts is not allowed
|
|
Additional property shellPods is not allowed
|
|
Invalid type. Expected: boolean, given: string`,
|
|
},
|
|
}
|
|
|
|
for k := range uu {
|
|
u := uu[k]
|
|
t.Run(k, func(t *testing.T) {
|
|
cfg := config.NewConfig(nil)
|
|
if err := cfg.Load(u.f, true); err != nil {
|
|
assert.Equal(t, u.err, err.Error())
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestConfigSetCurrentContext(t *testing.T) {
|
|
uu := map[string]struct {
|
|
cl, ct string
|
|
err string
|
|
}{
|
|
"happy": {
|
|
ct: "ct-1-2",
|
|
cl: "cl-1",
|
|
},
|
|
"toast": {
|
|
ct: "fred",
|
|
cl: "cl-1",
|
|
err: `set current context failed. no context found for: "fred"`,
|
|
},
|
|
}
|
|
|
|
for k := range uu {
|
|
u := uu[k]
|
|
t.Run(k, func(t *testing.T) {
|
|
cfg := mock.NewMockConfig()
|
|
ct, err := cfg.SetCurrentContext(u.ct)
|
|
if err != nil {
|
|
assert.Equal(t, u.err, err.Error())
|
|
return
|
|
}
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, u.cl, ct.ClusterName)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestConfigCurrentContext(t *testing.T) {
|
|
var (
|
|
cfgFile = "testdata/kubes/test.yaml"
|
|
ct2 = "ct-1-2"
|
|
)
|
|
|
|
uu := map[string]struct {
|
|
flags *genericclioptions.ConfigFlags
|
|
err error
|
|
context string
|
|
cluster string
|
|
namespace string
|
|
}{
|
|
"override-context": {
|
|
flags: &genericclioptions.ConfigFlags{
|
|
KubeConfig: &cfgFile,
|
|
Context: &ct2,
|
|
},
|
|
cluster: "cl-1",
|
|
context: "ct-1-2",
|
|
namespace: "ns-2",
|
|
},
|
|
"use-current-context": {
|
|
flags: &genericclioptions.ConfigFlags{
|
|
KubeConfig: &cfgFile,
|
|
},
|
|
cluster: "cl-1",
|
|
context: "ct-1-1",
|
|
namespace: client.DefaultNamespace,
|
|
},
|
|
}
|
|
|
|
for k := range uu {
|
|
u := uu[k]
|
|
t.Run(k, func(t *testing.T) {
|
|
cfg := mock.NewMockConfig()
|
|
|
|
err := cfg.Refine(u.flags, nil, client.NewConfig(u.flags))
|
|
assert.NoError(t, err)
|
|
ct, err := cfg.CurrentContext()
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, u.cluster, ct.ClusterName)
|
|
assert.Equal(t, u.namespace, ct.Namespace.Active)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestConfigRefine(t *testing.T) {
|
|
var (
|
|
cfgFile = "testdata/kubes/test.yaml"
|
|
cl1 = "cl-1"
|
|
ct2 = "ct-1-2"
|
|
ns1, ns2, nsx = "ns-1", "ns-2", "ns-x"
|
|
true = true
|
|
)
|
|
|
|
uu := map[string]struct {
|
|
flags *genericclioptions.ConfigFlags
|
|
k9sFlags *config.Flags
|
|
err string
|
|
context string
|
|
cluster string
|
|
namespace string
|
|
}{
|
|
"no-override": {
|
|
namespace: "default",
|
|
},
|
|
"override-cluster": {
|
|
flags: &genericclioptions.ConfigFlags{
|
|
KubeConfig: &cfgFile,
|
|
ClusterName: &cl1,
|
|
},
|
|
cluster: "cl-1",
|
|
context: "ct-1-1",
|
|
namespace: client.DefaultNamespace,
|
|
},
|
|
"override-cluster-context": {
|
|
flags: &genericclioptions.ConfigFlags{
|
|
KubeConfig: &cfgFile,
|
|
ClusterName: &cl1,
|
|
Context: &ct2,
|
|
},
|
|
cluster: "cl-1",
|
|
context: "ct-1-2",
|
|
namespace: "ns-2",
|
|
},
|
|
"override-bad-cluster": {
|
|
flags: &genericclioptions.ConfigFlags{
|
|
KubeConfig: &cfgFile,
|
|
ClusterName: &ns1,
|
|
},
|
|
cluster: "cl-1",
|
|
context: "ct-1-1",
|
|
namespace: client.DefaultNamespace,
|
|
},
|
|
"override-ns": {
|
|
flags: &genericclioptions.ConfigFlags{
|
|
KubeConfig: &cfgFile,
|
|
Namespace: &ns2,
|
|
},
|
|
cluster: "cl-1",
|
|
context: "ct-1-1",
|
|
namespace: "ns-2",
|
|
},
|
|
"all-ns": {
|
|
flags: &genericclioptions.ConfigFlags{
|
|
KubeConfig: &cfgFile,
|
|
Namespace: &ns2,
|
|
},
|
|
k9sFlags: &config.Flags{
|
|
AllNamespaces: &true,
|
|
},
|
|
cluster: "cl-1",
|
|
context: "ct-1-1",
|
|
namespace: client.NamespaceAll,
|
|
},
|
|
|
|
"override-bad-ns": {
|
|
flags: &genericclioptions.ConfigFlags{
|
|
KubeConfig: &cfgFile,
|
|
Namespace: &nsx,
|
|
},
|
|
cluster: "cl-1",
|
|
context: "ct-1-1",
|
|
namespace: "ns-x",
|
|
},
|
|
"override-context": {
|
|
flags: &genericclioptions.ConfigFlags{
|
|
KubeConfig: &cfgFile,
|
|
Context: &ct2,
|
|
},
|
|
cluster: "cl-1",
|
|
context: "ct-1-2",
|
|
namespace: "ns-2",
|
|
},
|
|
"override-bad-context": {
|
|
flags: &genericclioptions.ConfigFlags{
|
|
KubeConfig: &cfgFile,
|
|
Context: &ns1,
|
|
},
|
|
err: `k8sflags. unable to activate context "ns-1": no context found for: "ns-1"`,
|
|
},
|
|
"use-current-context": {
|
|
flags: &genericclioptions.ConfigFlags{
|
|
KubeConfig: &cfgFile,
|
|
},
|
|
cluster: "cl-1",
|
|
context: "ct-1-1",
|
|
namespace: client.DefaultNamespace,
|
|
},
|
|
}
|
|
|
|
for k := range uu {
|
|
u := uu[k]
|
|
t.Run(k, func(t *testing.T) {
|
|
cfg := mock.NewMockConfig()
|
|
|
|
err := cfg.Refine(u.flags, u.k9sFlags, client.NewConfig(u.flags))
|
|
if err != nil {
|
|
assert.Equal(t, u.err, err.Error())
|
|
} else {
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, u.context, cfg.K9s.ActiveContextName())
|
|
assert.Equal(t, u.namespace, cfg.ActiveNamespace())
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestConfigValidate(t *testing.T) {
|
|
cfg := mock.NewMockConfig()
|
|
cfg.SetConnection(mock.NewMockConnection())
|
|
|
|
assert.Nil(t, cfg.Load("testdata/configs/k9s.yaml", true))
|
|
cfg.Validate()
|
|
}
|
|
|
|
func TestConfigLoad(t *testing.T) {
|
|
cfg := mock.NewMockConfig()
|
|
|
|
assert.Nil(t, cfg.Load("testdata/configs/k9s.yaml", true))
|
|
assert.Equal(t, 2, cfg.K9s.RefreshRate)
|
|
assert.Equal(t, int64(200), cfg.K9s.Logger.TailCount)
|
|
assert.Equal(t, 2000, cfg.K9s.Logger.BufferSize)
|
|
}
|
|
|
|
func TestConfigLoadCrap(t *testing.T) {
|
|
cfg := mock.NewMockConfig()
|
|
|
|
assert.NotNil(t, cfg.Load("testdata/configs/k9s_not_there.yaml", true))
|
|
}
|
|
|
|
func TestConfigSaveFile(t *testing.T) {
|
|
cfg := mock.NewMockConfig()
|
|
|
|
assert.Nil(t, cfg.Load("testdata/configs/k9s.yaml", true))
|
|
|
|
cfg.K9s.RefreshRate = 100
|
|
cfg.K9s.ReadOnly = true
|
|
cfg.K9s.Logger.TailCount = 500
|
|
cfg.K9s.Logger.BufferSize = 800
|
|
cfg.Validate()
|
|
|
|
path := filepath.Join("/tmp", "k9s.yaml")
|
|
assert.NoError(t, cfg.SaveFile(path))
|
|
raw, err := os.ReadFile(path)
|
|
assert.Nil(t, err)
|
|
ee, err := os.ReadFile("testdata/configs/expected.yaml")
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, string(ee), string(raw))
|
|
}
|
|
|
|
func TestConfigReset(t *testing.T) {
|
|
cfg := mock.NewMockConfig()
|
|
assert.Nil(t, cfg.Load("testdata/configs/k9s.yaml", true))
|
|
cfg.Reset()
|
|
cfg.Validate()
|
|
|
|
path := filepath.Join("/tmp", "k9s.yaml")
|
|
assert.NoError(t, cfg.SaveFile(path))
|
|
|
|
bb, err := os.ReadFile(path)
|
|
assert.Nil(t, err)
|
|
ee, err := os.ReadFile("testdata/configs/k9s.yaml")
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, string(ee), string(bb))
|
|
}
|
|
|
|
// Helpers...
|
|
|
|
func TestSetup(t *testing.T) {
|
|
m.RegisterMockTestingT(t)
|
|
m.RegisterMockFailHandler(func(m string, i ...int) {
|
|
fmt.Println("Boom!", m, i)
|
|
})
|
|
}
|