diff --git a/Makefile b/Makefile
index 2a42a91a..99c87e6f 100644
--- a/Makefile
+++ b/Makefile
@@ -11,7 +11,7 @@ DATE ?= $(shell TZ=UTC date -j -f "%s" ${SOURCE_DATE_EPOCH} +"%Y-%m-%dT%H:
else
DATE ?= $(shell date -u -d @${SOURCE_DATE_EPOCH} +"%Y-%m-%dT%H:%M:%SZ")
endif
-VERSION ?= v0.50.0
+VERSION ?= v0.50.1
IMG_NAME := derailed/k9s
IMAGE := ${IMG_NAME}:${VERSION}
diff --git a/change_logs/release_v0.50.1.md b/change_logs/release_v0.50.1.md
new file mode 100644
index 00000000..32f707a2
--- /dev/null
+++ b/change_logs/release_v0.50.1.md
@@ -0,0 +1,42 @@
+
+
+# Release v0.51
+
+## Notes
+
+Thank you to all that contributed with flushing out issues and enhancements for K9s!
+I'll try to mark some of these issues as fixed. But if you don't mind grab the latest rev
+and see if we're happier with some of the fixes!
+If you've filed an issue please help me verify and close.
+
+Your support, kindness and awesome suggestions to make K9s better are, as ever, very much noted and appreciated!
+Also big thanks to all that have allocated their own time to help others on both slack and on this repo!!
+
+As you may know, K9s is not pimped out by corps with deep pockets, thus if you feel K9s is helping your Kubernetes journey,
+please consider joining our [sponsorship program](https://github.com/sponsors/derailed) and/or make some noise on social! [@kitesurfer](https://twitter.com/kitesurfer)
+
+On Slack? Please join us [K9slackers](https://join.slack.com/t/k9sers/shared_invite/enQtOTA5MDEyNzI5MTU0LWQ1ZGI3MzliYzZhZWEyNzYxYzA3NjE0YTk1YmFmNzViZjIyNzhkZGI0MmJjYzhlNjdlMGJhYzE2ZGU1NjkyNTM)
+
+## 5-0, 5-0 HotFix!
+
+It looks like we've broken a few things in the clean up process 😳
+Apologizes for the `disruption in the farce`. Hopefully happier on v0.50.1...
+Crossing fingers and toes!
+
+☠️ Careful on this upgrade! 🏴☠️
+We've gone thru lots of code revamp/refactor in the v0.50.0, so mileage may vary...
+
+---
+
+## Resolved Issues
+
+* [#3262](https://github.com/derailed/k9s/issues/3262) Crash when no shellPod is defined in config file
+* [#3261](https://github.com/derailed/k9s/issues/3261) aliases with namespace and/or labels produce an error
+* [#3258](https://github.com/derailed/k9s/issues/3258) mac silicon 0.50.0 runtime error
+* [#3257](https://github.com/derailed/k9s/issues/3257) pods are reported to run on nodes they are not running on
+* [#3256](https://github.com/derailed/k9s/issues/3256) Pods view seems broken in 0.50.0
+* [#3255](https://github.com/derailed/k9s/issues/3255) Custom view does not work randomly
+
+
+---
+
© 2025 Imhotep Software LLC. All materials licensed under [Apache v2.0](http://www.apache.org/licenses/LICENSE-2.0)
\ No newline at end of file
diff --git a/internal/client/gvr.go b/internal/client/gvr.go
index f1ea041c..f8f944b6 100644
--- a/internal/client/gvr.go
+++ b/internal/client/gvr.go
@@ -71,6 +71,10 @@ func NewGVR(path string) *GVR {
return &gvr
}
+func (g *GVR) IsCommand() bool {
+ return g != nil && strings.Contains(g.raw, " ")
+}
+
func (g *GVR) IsK8sRes() bool {
return strings.Contains(g.raw, "/")
}
diff --git a/internal/config/alias.go b/internal/config/alias.go
index 05d85cdd..2f506ff6 100644
--- a/internal/config/alias.go
+++ b/internal/config/alias.go
@@ -5,7 +5,6 @@ package config
import (
"errors"
- "fmt"
"io/fs"
"log/slog"
"os"
@@ -15,6 +14,7 @@ import (
"github.com/derailed/k9s/internal/config/data"
"github.com/derailed/k9s/internal/config/json"
"github.com/derailed/k9s/internal/slogs"
+ "github.com/derailed/k9s/internal/view/cmd"
"gopkg.in/yaml.v3"
"k8s.io/apimachinery/pkg/util/sets"
)
@@ -79,26 +79,35 @@ func (a *Aliases) Clear() {
}
}
+func (a *Aliases) Resolve(command string) (*client.GVR, string, bool) {
+ agvr, ok := a.Get(command)
+ if !ok {
+ return nil, "", false
+ }
+ if agvr.IsCommand() {
+ p := cmd.NewInterpreter(agvr.String())
+ gvr, ok := a.Get(p.Cmd())
+ if !ok {
+ return nil, "", false
+ }
+ return gvr, p.Args(), true
+ }
+
+ return agvr, "", true
+}
+
// Get retrieves an alias.
func (a *Aliases) Get(alias string) (*client.GVR, bool) {
a.mx.RLock()
defer a.mx.RUnlock()
gvr, ok := a.Alias[alias]
- if ok && !gvr.IsK8sRes() {
- if rgvr, found := a.Alias[gvr.String()]; found {
- return rgvr, found
- }
- }
return gvr, ok
}
// Define declares a new alias.
func (a *Aliases) Define(gvr *client.GVR, aliases ...string) {
- if gvr.String() == "deployment" {
- fmt.Println("!!YO!!")
- }
a.mx.Lock()
defer a.mx.Unlock()
for _, alias := range aliases {
diff --git a/internal/config/config_test.go b/internal/config/config_test.go
index 031eb742..37f5ee0b 100644
--- a/internal/config/config_test.go
+++ b/internal/config/config_test.go
@@ -53,7 +53,7 @@ func TestConfigSave(t *testing.T) {
xdg.Reload()
u := uu[k]
t.Run(k, func(t *testing.T) {
- c := mock.NewMockConfig()
+ c := mock.NewMockConfig(t)
_, err := c.K9s.ActivateContext(u.ct)
require.NoError(t, err)
if u.flags != nil {
@@ -113,7 +113,7 @@ func TestSetActiveView(t *testing.T) {
for k := range uu {
u := uu[k]
t.Run(k, func(t *testing.T) {
- c := mock.NewMockConfig()
+ c := mock.NewMockConfig(t)
_, _ = c.K9s.ActivateContext(u.ct)
if u.flags != nil {
require.NoError(t, c.Refine(u.flags, nil, client.NewConfig(u.flags)))
@@ -156,7 +156,7 @@ func TestActiveContextName(t *testing.T) {
for k := range uu {
u := uu[k]
t.Run(k, func(t *testing.T) {
- c := mock.NewMockConfig()
+ c := mock.NewMockConfig(t)
_, _ = c.K9s.ActivateContext(u.ct)
if u.flags != nil {
require.NoError(t, c.Refine(u.flags, nil, client.NewConfig(u.flags)))
@@ -182,14 +182,22 @@ func TestActiveView(t *testing.T) {
"empty": {
e: data.DefaultView,
},
+
"not-exists": {
ct: "fred",
e: data.DefaultView,
},
+
"happy": {
ct: "ct-1-1",
e: data.DefaultView,
},
+
+ "happy1": {
+ ct: "ct-1-2",
+ e: data.DefaultView,
+ },
+
"cli-override": {
flags: &genericclioptions.ConfigFlags{
KubeConfig: &cfgFile,
@@ -204,7 +212,7 @@ func TestActiveView(t *testing.T) {
for k := range uu {
u := uu[k]
t.Run(k, func(t *testing.T) {
- c := mock.NewMockConfig()
+ c := mock.NewMockConfig(t)
_, _ = c.K9s.ActivateContext(u.ct)
if u.flags != nil {
require.NoError(t, c.Refine(u.flags, nil, client.NewConfig(u.flags)))
@@ -233,7 +241,7 @@ func TestFavNamespaces(t *testing.T) {
for k := range uu {
u := uu[k]
t.Run(k, func(t *testing.T) {
- c := mock.NewMockConfig()
+ c := mock.NewMockConfig(t)
_, _ = c.K9s.ActivateContext(u.ct)
assert.Equal(t, u.e, c.FavNamespaces())
})
@@ -258,7 +266,7 @@ func TestContextAliasesPath(t *testing.T) {
for k := range uu {
u := uu[k]
t.Run(k, func(t *testing.T) {
- c := mock.NewMockConfig()
+ c := mock.NewMockConfig(t)
_, _ = c.K9s.ActivateContext(u.ct)
assert.Equal(t, u.e, c.ContextAliasesPath())
})
@@ -286,7 +294,7 @@ func TestContextPluginsPath(t *testing.T) {
for k := range uu {
u := uu[k]
t.Run(k, func(t *testing.T) {
- c := mock.NewMockConfig()
+ c := mock.NewMockConfig(t)
_, _ = c.K9s.ActivateContext(u.ct)
s, err := c.ContextPluginsPath()
if err != nil {
@@ -344,7 +352,7 @@ func TestConfigActivateContext(t *testing.T) {
for k := range uu {
u := uu[k]
t.Run(k, func(t *testing.T) {
- cfg := mock.NewMockConfig()
+ cfg := mock.NewMockConfig(t)
ct, err := cfg.ActivateContext(u.ct)
if err != nil {
assert.Equal(t, u.err, err.Error())
@@ -391,7 +399,7 @@ func TestConfigCurrentContext(t *testing.T) {
for k := range uu {
u := uu[k]
t.Run(k, func(t *testing.T) {
- cfg := mock.NewMockConfig()
+ cfg := mock.NewMockConfig(t)
err := cfg.Refine(u.flags, nil, client.NewConfig(u.flags))
require.NoError(t, err)
@@ -511,7 +519,7 @@ func TestConfigRefine(t *testing.T) {
for k := range uu {
u := uu[k]
t.Run(k, func(t *testing.T) {
- cfg := mock.NewMockConfig()
+ cfg := mock.NewMockConfig(t)
err := cfg.Refine(u.flags, u.k9sFlags, client.NewConfig(u.flags))
if err != nil {
@@ -526,7 +534,7 @@ func TestConfigRefine(t *testing.T) {
}
func TestConfigValidate(t *testing.T) {
- cfg := mock.NewMockConfig()
+ cfg := mock.NewMockConfig(t)
cfg.SetConnection(mock.NewMockConnection())
require.NoError(t, cfg.Load("testdata/configs/k9s.yaml", true))
@@ -534,7 +542,7 @@ func TestConfigValidate(t *testing.T) {
}
func TestConfigLoad(t *testing.T) {
- cfg := mock.NewMockConfig()
+ cfg := mock.NewMockConfig(t)
require.NoError(t, cfg.Load("testdata/configs/k9s.yaml", true))
assert.Equal(t, 2, cfg.K9s.RefreshRate)
@@ -543,13 +551,13 @@ func TestConfigLoad(t *testing.T) {
}
func TestConfigLoadCrap(t *testing.T) {
- cfg := mock.NewMockConfig()
+ cfg := mock.NewMockConfig(t)
assert.Error(t, cfg.Load("testdata/configs/k9s_not_there.yaml", true))
}
func TestConfigSaveFile(t *testing.T) {
- cfg := mock.NewMockConfig()
+ cfg := mock.NewMockConfig(t)
require.NoError(t, cfg.Load("testdata/configs/k9s.yaml", true))
@@ -570,7 +578,7 @@ func TestConfigSaveFile(t *testing.T) {
}
func TestConfigReset(t *testing.T) {
- cfg := mock.NewMockConfig()
+ cfg := mock.NewMockConfig(t)
require.NoError(t, cfg.Load("testdata/configs/k9s.yaml", true))
cfg.Reset()
cfg.Validate("ct-1-1", "cl-1")
diff --git a/internal/config/data/context_test.go b/internal/config/data/context_test.go
index 8f313df5..21e4cffd 100644
--- a/internal/config/data/context_test.go
+++ b/internal/config/data/context_test.go
@@ -15,7 +15,7 @@ func TestClusterValidate(t *testing.T) {
c := data.NewContext()
c.Validate(mock.NewMockConnection(), "ct-1", "cl-1")
- assert.Equal(t, "po", c.View.Active)
+ assert.Equal(t, data.DefaultView, c.View.Active)
assert.Equal(t, "default", c.Namespace.Active)
assert.Len(t, c.Namespace.Favorites, 1)
assert.Equal(t, []string{"default"}, c.Namespace.Favorites)
@@ -25,7 +25,7 @@ func TestClusterValidateEmpty(t *testing.T) {
c := data.NewContext()
c.Validate(mock.NewMockConnection(), "ct-1", "cl-1")
- assert.Equal(t, "po", c.View.Active)
+ assert.Equal(t, data.DefaultView, c.View.Active)
assert.Equal(t, "default", c.Namespace.Active)
assert.Len(t, c.Namespace.Favorites, 1)
assert.Equal(t, []string{"default"}, c.Namespace.Favorites)
diff --git a/internal/config/k9s.go b/internal/config/k9s.go
index df2752de..f32e0dfa 100644
--- a/internal/config/k9s.go
+++ b/internal/config/k9s.go
@@ -386,7 +386,9 @@ func (k *K9s) Validate(c client.Connection, contextName, clusterName string) {
if k.getActiveConfig() == nil {
_, _ = k.ActivateContext(contextName)
}
- k.ShellPod.Validate()
+ if k.ShellPod != nil {
+ k.ShellPod.Validate()
+ }
k.Logger = k.Logger.Validate()
k.Thresholds = k.Thresholds.Validate()
diff --git a/internal/config/k9s_test.go b/internal/config/k9s_test.go
index 6afc155a..d4bd21eb 100644
--- a/internal/config/k9s_test.go
+++ b/internal/config/k9s_test.go
@@ -133,7 +133,7 @@ func TestK9sMerge(t *testing.T) {
}
func TestContextScreenDumpDir(t *testing.T) {
- cfg := mock.NewMockConfig()
+ cfg := mock.NewMockConfig(t)
_, err := cfg.K9s.ActivateContext("ct-1-1")
require.NoError(t, err)
@@ -142,7 +142,7 @@ func TestContextScreenDumpDir(t *testing.T) {
}
func TestAppScreenDumpDir(t *testing.T) {
- cfg := mock.NewMockConfig()
+ cfg := mock.NewMockConfig(t)
require.NoError(t, cfg.Load("testdata/configs/k9s.yaml", true))
assert.Equal(t, "/tmp/k9s-test/screen-dumps", cfg.K9s.AppScreenDumpDir())
diff --git a/internal/config/mock/test_helpers.go b/internal/config/mock/test_helpers.go
index 97ab1f65..10dcdf53 100644
--- a/internal/config/mock/test_helpers.go
+++ b/internal/config/mock/test_helpers.go
@@ -11,9 +11,11 @@ import (
"net/url"
"os"
"strings"
+ "testing"
"github.com/derailed/k9s/internal/client"
"github.com/derailed/k9s/internal/config"
+ "github.com/stretchr/testify/require"
version "k8s.io/apimachinery/pkg/version"
"k8s.io/cli-runtime/pkg/genericclioptions"
disk "k8s.io/client-go/discovery/cached/disk"
@@ -35,9 +37,11 @@ func EnsureDir(d string) error {
return os.MkdirAll(d, 0700)
}
-func NewMockConfig() *config.Config {
- if _, err := os.Stat("/tmp/test"); errors.Is(err, os.ErrExist) {
- _ = os.RemoveAll("/tmp/test")
+func NewMockConfig(t testing.TB) *config.Config {
+ if _, err := os.Stat("/tmp/test"); err == nil {
+ if e := os.RemoveAll("/tmp/test"); e != nil {
+ require.NoError(t, e)
+ }
}
config.AppContextsDir = "/tmp/test"
cl, ct := "cl-1", "ct-1-1"
diff --git a/internal/dao/alias.go b/internal/dao/alias.go
index c6f48b20..651d22a1 100644
--- a/internal/dao/alias.go
+++ b/internal/dao/alias.go
@@ -63,14 +63,7 @@ func (*Alias) List(ctx context.Context, _ string) ([]runtime.Object, error) {
// AsGVR returns a matching gvr if it exists.
func (a *Alias) AsGVR(alias string) (*client.GVR, string, bool) {
- gvr, ok := a.Aliases.Get(alias)
- if ok {
- if pgvr := MetaAccess.Lookup(alias); pgvr != client.NoGVR {
- return pgvr, "", ok
- }
- }
-
- return gvr, "", ok
+ return a.Resolve(alias)
}
// Get fetch a resource.
@@ -106,10 +99,9 @@ func (a *Alias) load(path string) error {
}
a.Define(gvr, gvr.AsResourceName())
- // Allow single shot commands for k8s resources only!
- if isStandardGroup(gvr.GVSub()) {
- a.Define(gvr, meta.Name)
- a.Define(gvr, meta.SingularName)
+ // Allow single shot commands for k8s resources only expect for metrics resource which override pods and nodes ;(!
+ if isStandardGroup(gvr.GVSub()) && gvr.G() != "metrics.k8s.io" {
+ a.Define(gvr, meta.Name, meta.SingularName)
}
if len(meta.ShortNames) > 0 {
a.Define(gvr, meta.ShortNames...)
diff --git a/internal/dao/alias_test.go b/internal/dao/alias_test.go
index 0d59ee08..7cd41f9a 100644
--- a/internal/dao/alias_test.go
+++ b/internal/dao/alias_test.go
@@ -20,39 +20,60 @@ func TestAsGVR(t *testing.T) {
a := dao.NewAlias(makeFactory())
a.Define(client.PodGVR, "po", "pod", "pods")
a.Define(client.WkGVR, client.WkGVR.String(), "workload", "wkl")
+ a.Define(client.NewGVR("pod default"), "pp")
+ a.Define(client.NewGVR("pod default @fred"), "ppc")
uu := map[string]struct {
cmd string
ok bool
gvr *client.GVR
+ exp string
}{
"ok": {
cmd: "pods",
ok: true,
gvr: client.PodGVR,
},
+
"ok-short": {
cmd: "po",
ok: true,
gvr: client.PodGVR,
},
+
"missing": {
cmd: "zorg",
},
+
"alias": {
cmd: "wkl",
ok: true,
gvr: client.WkGVR,
},
+
+ "ns-alias": {
+ cmd: "pp",
+ ok: true,
+ gvr: client.PodGVR,
+ exp: "default",
+ },
+
+ "full-alias": {
+ cmd: "ppc",
+ ok: true,
+ gvr: client.PodGVR,
+ exp: "default @fred",
+ },
}
for k := range uu {
u := uu[k]
t.Run(k, func(t *testing.T) {
- gvr, _, ok := a.AsGVR(u.cmd)
+ gvr, exp, ok := a.AsGVR(u.cmd)
assert.Equal(t, u.ok, ok)
if u.ok {
assert.Equal(t, u.gvr, gvr)
+ assert.Equal(t, u.exp, exp)
}
})
}
diff --git a/internal/render/pod.go b/internal/render/pod.go
index 0c8b0d2d..5aa5ca9a 100644
--- a/internal/render/pod.go
+++ b/internal/render/pod.go
@@ -7,7 +7,6 @@ import (
"fmt"
"strconv"
"strings"
- "time"
"github.com/derailed/k9s/internal/client"
"github.com/derailed/k9s/internal/model1"
@@ -19,7 +18,6 @@ import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
- "k8s.io/apimachinery/pkg/util/cache"
mv1beta1 "k8s.io/metrics/pkg/apis/metrics/v1beta1"
)
@@ -76,22 +74,15 @@ var defaultPodHeader = model1.Header{
model1.HeaderColumn{Name: "AGE", Attrs: model1.Attrs{Time: true}},
}
-const (
- cacheSize = 5_000
- expiration = 5 * time.Minute
-)
-
// Pod renders a K8s Pod to screen.
type Pod struct {
*Base
- cache *cache.LRUExpireCache
}
// NewPod returns a new instance.
func NewPod() *Pod {
return &Pod{
- Base: new(Base),
- cache: cache.NewLRUExpireCache(cacheSize),
+ Base: new(Base),
}
}
@@ -157,22 +148,9 @@ func (p *Pod) defaultRow(pwm *PodWithMetrics, row *model1.Row) error {
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(pwm.Raw.Object["status"].(map[string]any), &st); err != nil {
return err
}
- key := pwm.Raw.GetUID()
- for _, o := range pwm.Raw.GetOwnerReferences() {
- if o.Controller != nil && *o.Controller {
- key = o.UID
- break
- }
- }
-
spec := new(v1.PodSpec)
- if cspec, ok := p.cache.Get(key); ok {
- spec = cspec.(*v1.PodSpec)
- } else {
- if err := runtime.DefaultUnstructuredConverter.FromUnstructured(pwm.Raw.Object["spec"].(map[string]any), spec); err != nil {
- return err
- }
- p.cache.Add(key, spec, expiration)
+ if err := runtime.DefaultUnstructuredConverter.FromUnstructured(pwm.Raw.Object["spec"].(map[string]any), spec); err != nil {
+ return err
}
dt := pwm.Raw.GetDeletionTimestamp()
diff --git a/internal/ui/app_test.go b/internal/ui/app_test.go
index 0725561a..eb1934e8 100644
--- a/internal/ui/app_test.go
+++ b/internal/ui/app_test.go
@@ -12,7 +12,7 @@ import (
)
func TestAppGetCmd(t *testing.T) {
- a := ui.NewApp(mock.NewMockConfig(), "")
+ a := ui.NewApp(mock.NewMockConfig(t), "")
a.Init()
a.CmdBuff().SetText("blee", "")
@@ -20,7 +20,7 @@ func TestAppGetCmd(t *testing.T) {
}
func TestAppInCmdMode(t *testing.T) {
- a := ui.NewApp(mock.NewMockConfig(), "")
+ a := ui.NewApp(mock.NewMockConfig(t), "")
a.Init()
a.CmdBuff().SetText("blee", "")
assert.False(t, a.InCmdMode())
@@ -30,7 +30,7 @@ func TestAppInCmdMode(t *testing.T) {
}
func TestAppResetCmd(t *testing.T) {
- a := ui.NewApp(mock.NewMockConfig(), "")
+ a := ui.NewApp(mock.NewMockConfig(t), "")
a.Init()
a.CmdBuff().SetText("blee", "")
@@ -40,7 +40,7 @@ func TestAppResetCmd(t *testing.T) {
}
func TestAppHasCmd(t *testing.T) {
- a := ui.NewApp(mock.NewMockConfig(), "")
+ a := ui.NewApp(mock.NewMockConfig(t), "")
a.Init()
a.ActivateCmd(true)
@@ -51,7 +51,7 @@ func TestAppHasCmd(t *testing.T) {
}
func TestAppGetActions(t *testing.T) {
- a := ui.NewApp(mock.NewMockConfig(), "")
+ a := ui.NewApp(mock.NewMockConfig(t), "")
a.Init()
a.GetActions().Add(ui.KeyZ, ui.KeyAction{Description: "zorg"})
@@ -60,7 +60,7 @@ func TestAppGetActions(t *testing.T) {
}
func TestAppViews(t *testing.T) {
- a := ui.NewApp(mock.NewMockConfig(), "")
+ a := ui.NewApp(mock.NewMockConfig(t), "")
a.Init()
vv := []string{"crumbs", "logo", "prompt", "menu"}
diff --git a/internal/ui/config_test.go b/internal/ui/config_test.go
index 9bc34292..9b1967ab 100644
--- a/internal/ui/config_test.go
+++ b/internal/ui/config_test.go
@@ -33,7 +33,7 @@ func TestSkinnedContext(t *testing.T) {
require.NoError(t, os.WriteFile(tf, raw, data.DefaultFileMod))
var cfg ui.Configurator
- cfg.Config = mock.NewMockConfig()
+ cfg.Config = mock.NewMockConfig(t)
cl, ct := "cl-1", "ct-1"
flags := genericclioptions.ConfigFlags{
ClusterName: &cl,
diff --git a/internal/ui/flash_test.go b/internal/ui/flash_test.go
index 5122152e..92bc48e6 100644
--- a/internal/ui/flash_test.go
+++ b/internal/ui/flash_test.go
@@ -25,7 +25,7 @@ func TestFlash(t *testing.T) {
"err": {l: model.FlashErr, i: "hello", e: "😡 hello\n"},
}
- a := ui.NewApp(mock.NewMockConfig(), "test")
+ a := ui.NewApp(mock.NewMockConfig(t), "test")
f := ui.NewFlash(a)
f.SetTestMode(true)
ctx, cancel := context.WithCancel(context.Background())
diff --git a/internal/ui/indicator_test.go b/internal/ui/indicator_test.go
index 40032517..3e67714b 100644
--- a/internal/ui/indicator_test.go
+++ b/internal/ui/indicator_test.go
@@ -13,7 +13,7 @@ import (
)
func TestIndicatorReset(t *testing.T) {
- i := ui.NewStatusIndicator(ui.NewApp(mock.NewMockConfig(), ""), config.NewStyles())
+ i := ui.NewStatusIndicator(ui.NewApp(mock.NewMockConfig(t), ""), config.NewStyles())
i.SetPermanent("Blee")
i.Info("duh")
i.Reset()
@@ -22,21 +22,21 @@ func TestIndicatorReset(t *testing.T) {
}
func TestIndicatorInfo(t *testing.T) {
- i := ui.NewStatusIndicator(ui.NewApp(mock.NewMockConfig(), ""), config.NewStyles())
+ i := ui.NewStatusIndicator(ui.NewApp(mock.NewMockConfig(t), ""), config.NewStyles())
i.Info("Blee")
assert.Equal(t, "[lawngreen::b] \n", i.GetText(false))
}
func TestIndicatorWarn(t *testing.T) {
- i := ui.NewStatusIndicator(ui.NewApp(mock.NewMockConfig(), ""), config.NewStyles())
+ i := ui.NewStatusIndicator(ui.NewApp(mock.NewMockConfig(t), ""), config.NewStyles())
i.Warn("Blee")
assert.Equal(t, "[mediumvioletred::b] \n", i.GetText(false))
}
func TestIndicatorErr(t *testing.T) {
- i := ui.NewStatusIndicator(ui.NewApp(mock.NewMockConfig(), ""), config.NewStyles())
+ i := ui.NewStatusIndicator(ui.NewApp(mock.NewMockConfig(t), ""), config.NewStyles())
i.Err("Blee")
assert.Equal(t, "[orangered::b] \n", i.GetText(false))
diff --git a/internal/view/alias_test.go b/internal/view/alias_test.go
index 06a611a6..09a959ad 100644
--- a/internal/view/alias_test.go
+++ b/internal/view/alias_test.go
@@ -27,14 +27,14 @@ import (
func TestAliasNew(t *testing.T) {
v := view.NewAlias(client.AliGVR)
- require.NoError(t, v.Init(makeContext()))
+ require.NoError(t, v.Init(makeContext(t)))
assert.Equal(t, "Aliases", v.Name())
assert.Len(t, v.Hints(), 6)
}
func TestAliasSearch(t *testing.T) {
v := view.NewAlias(client.AliGVR)
- require.NoError(t, v.Init(makeContext()))
+ require.NoError(t, v.Init(makeContext(t)))
v.GetTable().SetModel(&mockModel{})
v.GetTable().Refresh()
v.App().Prompt().SetModel(v.GetTable().CmdBuff())
@@ -46,7 +46,7 @@ func TestAliasSearch(t *testing.T) {
func TestAliasGoto(t *testing.T) {
v := view.NewAlias(client.AliGVR)
- require.NoError(t, v.Init(makeContext()))
+ require.NoError(t, v.Init(makeContext(t)))
v.GetTable().Select(0, 0)
b := buffL{}
@@ -74,8 +74,8 @@ func (b *buffL) BufferActive(bool, model.BufferKind) {
b.active++
}
-func makeContext() context.Context {
- a := view.NewApp(mock.NewMockConfig())
+func makeContext(t testing.TB) context.Context {
+ a := view.NewApp(mock.NewMockConfig(t))
ctx := context.WithValue(context.Background(), internal.KeyApp, a)
return context.WithValue(ctx, internal.KeyStyles, a.Styles)
}
diff --git a/internal/view/app.go b/internal/view/app.go
index 8735b41c..a5bb8e9b 100644
--- a/internal/view/app.go
+++ b/internal/view/app.go
@@ -466,7 +466,7 @@ func (a *App) switchContext(ci *cmd.Interpreter, force bool) error {
p := cmd.NewInterpreter(a.Config.ActiveView())
p.ResetContextArg()
if p.IsContextCmd() {
- a.Config.SetActiveView("pod")
+ a.Config.SetActiveView(client.PodGVR.String())
}
ns := a.Config.ActiveNamespace()
if !a.Conn().IsValidNamespace(ns) {
diff --git a/internal/view/app_test.go b/internal/view/app_test.go
index f6b9663d..24d8d7fa 100644
--- a/internal/view/app_test.go
+++ b/internal/view/app_test.go
@@ -12,7 +12,7 @@ import (
)
func TestAppNew(t *testing.T) {
- a := view.NewApp(mock.NewMockConfig())
+ a := view.NewApp(mock.NewMockConfig(t))
_ = a.Init("blee", 10)
assert.Equal(t, 15, a.GetActions().Len())
diff --git a/internal/view/cm_test.go b/internal/view/cm_test.go
index 158484f8..c7c8bf80 100644
--- a/internal/view/cm_test.go
+++ b/internal/view/cm_test.go
@@ -15,7 +15,7 @@ import (
func TestConfigMapNew(t *testing.T) {
s := view.NewConfigMap(client.CmGVR)
- require.NoError(t, s.Init(makeCtx()))
+ require.NoError(t, s.Init(makeCtx(t)))
assert.Equal(t, "ConfigMaps", s.Name())
assert.Len(t, s.Hints(), 7)
}
diff --git a/internal/view/cmd/interpreter.go b/internal/view/cmd/interpreter.go
index beaf8c1f..9ca80ca7 100644
--- a/internal/view/cmd/interpreter.go
+++ b/internal/view/cmd/interpreter.go
@@ -48,6 +48,10 @@ func (c *Interpreter) Cmd() string {
return c.cmd
}
+func (c *Interpreter) Args() string {
+ return strings.TrimSpace(strings.Replace(c.line, c.cmd, "", 1))
+}
+
// IsBlank returns true if prompt is empty.
func (c *Interpreter) IsBlank() bool {
return c.line == ""
diff --git a/internal/view/command.go b/internal/view/command.go
index 4d44c842..2e746477 100644
--- a/internal/view/command.go
+++ b/internal/view/command.go
@@ -9,7 +9,6 @@ import (
"log/slog"
"regexp"
"runtime/debug"
- "strings"
"sync"
"github.com/derailed/k9s/internal/client"
@@ -21,7 +20,7 @@ import (
)
const (
- podCmd = "pod"
+ podCmd = "v1/pods"
ctxCmd = "ctx"
)
@@ -291,11 +290,7 @@ func (c *Command) viewMetaFor(p *cmd.Interpreter) (*client.GVR, *MetaViewer, err
return client.NoGVR, nil, fmt.Errorf("`%s` command not found", p.Cmd())
}
if exp != "" {
- ff := strings.Fields(exp)
- ff[0] = gvr.String()
- ap := cmd.NewInterpreter(strings.Join(ff, " "))
- gvr = client.NewGVR(ap.Cmd())
- p.Amend(ap)
+ p.Amend(cmd.NewInterpreter(gvr.String() + " " + exp))
}
v := MetaViewer{
diff --git a/internal/view/command_test.go b/internal/view/command_test.go
new file mode 100644
index 00000000..0007bac4
--- /dev/null
+++ b/internal/view/command_test.go
@@ -0,0 +1,71 @@
+package view
+
+import (
+ "errors"
+ "testing"
+
+ "github.com/derailed/k9s/internal/client"
+ "github.com/derailed/k9s/internal/config"
+ "github.com/derailed/k9s/internal/dao"
+ "github.com/derailed/k9s/internal/view/cmd"
+ "github.com/stretchr/testify/assert"
+)
+
+func Test_viewMetaFor(t *testing.T) {
+ uu := map[string]struct {
+ cmd string
+ gvr *client.GVR
+ err error
+ }{
+ "empty": {
+ cmd: "",
+ gvr: client.PodGVR,
+ err: errors.New("`` command not found"),
+ },
+
+ "toast-cmd": {
+ cmd: "v1/pd",
+ gvr: client.PodGVR,
+ err: errors.New("`v1/pd` command not found"),
+ },
+
+ "gvr-cmd": {
+ cmd: "v1/pods",
+ gvr: client.PodGVR,
+ err: errors.New("blah"),
+ },
+
+ "alias-cmd": {
+ cmd: "po",
+ gvr: client.PodGVR,
+ err: errors.New("blee"),
+ },
+
+ "full-cmd": {
+ cmd: "pdl",
+ gvr: client.PodGVR,
+ err: errors.New("blee"),
+ },
+ }
+
+ c := &Command{
+ alias: &dao.Alias{
+ Aliases: config.NewAliases(),
+ },
+ }
+ c.alias.Define(client.PodGVR, "po", "pod", "pods", client.PodGVR.String())
+ c.alias.Define(client.NewGVR("pod default"), "pd")
+ c.alias.Define(client.NewGVR("pod default app=blee @fred"), "pdl")
+
+ for k, u := range uu {
+ t.Run(k, func(t *testing.T) {
+ p := cmd.NewInterpreter(u.cmd)
+ gvr, _, err := c.viewMetaFor(p)
+ if err != nil {
+ assert.Equal(t, u.err.Error(), err.Error())
+ } else {
+ assert.Equal(t, u.gvr, gvr)
+ }
+ })
+ }
+}
diff --git a/internal/view/container_test.go b/internal/view/container_test.go
index 39c3abab..d46da494 100644
--- a/internal/view/container_test.go
+++ b/internal/view/container_test.go
@@ -15,7 +15,7 @@ import (
func TestContainerNew(t *testing.T) {
c := view.NewContainer(client.CoGVR)
- require.NoError(t, c.Init(makeCtx()))
+ require.NoError(t, c.Init(makeCtx(t)))
assert.Equal(t, "Containers", c.Name())
assert.Len(t, c.Hints(), 19)
}
diff --git a/internal/view/context_test.go b/internal/view/context_test.go
index 42fe5e60..3fac43b7 100644
--- a/internal/view/context_test.go
+++ b/internal/view/context_test.go
@@ -15,7 +15,7 @@ import (
func TestContext(t *testing.T) {
ctx := view.NewContext(client.CtGVR)
- require.NoError(t, ctx.Init(makeCtx()))
+ require.NoError(t, ctx.Init(makeCtx(t)))
assert.Equal(t, "Contexts", ctx.Name())
assert.Len(t, ctx.Hints(), 5)
}
diff --git a/internal/view/dir_test.go b/internal/view/dir_test.go
index f00dc355..53818dfa 100644
--- a/internal/view/dir_test.go
+++ b/internal/view/dir_test.go
@@ -14,7 +14,7 @@ import (
func TestDir(t *testing.T) {
v := view.NewDir("/fred")
- require.NoError(t, v.Init(makeCtx()))
+ require.NoError(t, v.Init(makeCtx(t)))
assert.Equal(t, "Directory", v.Name())
assert.Len(t, v.Hints(), 7)
}
diff --git a/internal/view/dp_test.go b/internal/view/dp_test.go
index 270646d1..43cfd594 100644
--- a/internal/view/dp_test.go
+++ b/internal/view/dp_test.go
@@ -15,7 +15,7 @@ import (
func TestDeploy(t *testing.T) {
v := view.NewDeploy(client.DpGVR)
- require.NoError(t, v.Init(makeCtx()))
+ require.NoError(t, v.Init(makeCtx(t)))
assert.Equal(t, "Deployments", v.Name())
assert.Len(t, v.Hints(), 16)
}
diff --git a/internal/view/ds_test.go b/internal/view/ds_test.go
index 62e8da20..9f2787cf 100644
--- a/internal/view/ds_test.go
+++ b/internal/view/ds_test.go
@@ -15,7 +15,7 @@ import (
func TestDaemonSet(t *testing.T) {
v := view.NewDaemonSet(client.DsGVR)
- require.NoError(t, v.Init(makeCtx()))
+ require.NoError(t, v.Init(makeCtx(t)))
assert.Equal(t, "DaemonSets", v.Name())
assert.Len(t, v.Hints(), 17)
}
diff --git a/internal/view/exec.go b/internal/view/exec.go
index 35b041b2..3ecc67f6 100644
--- a/internal/view/exec.go
+++ b/internal/view/exec.go
@@ -321,6 +321,11 @@ func launchNodeShell(v model.Igniter, a *App, node string) {
}
func launchPodShell(v model.Igniter, a *App) {
+ if a.Config.K9s.ShellPod == nil {
+ slog.Error("Shell pod not configured!")
+ return
+ }
+
defer func() {
if err := nukeK9sShell(a); err != nil {
a.Flash().Errf("Launching node shell failed: %s", err)
diff --git a/internal/view/help_test.go b/internal/view/help_test.go
index 1f850169..c43cc531 100644
--- a/internal/view/help_test.go
+++ b/internal/view/help_test.go
@@ -15,7 +15,7 @@ import (
)
func TestHelp(t *testing.T) {
- ctx := makeCtx()
+ ctx := makeCtx(t)
app := ctx.Value(internal.KeyApp).(*view.App)
po := view.NewPod(client.PodGVR)
diff --git a/internal/view/helpers_test.go b/internal/view/helpers_test.go
index 9f941178..1c1ddac4 100644
--- a/internal/view/helpers_test.go
+++ b/internal/view/helpers_test.go
@@ -61,7 +61,7 @@ func TestParsePFAnn(t *testing.T) {
}
func TestExtractApp(t *testing.T) {
- app := NewApp(mock.NewMockConfig())
+ app := NewApp(mock.NewMockConfig(t))
uu := map[string]struct {
app *App
diff --git a/internal/view/live_view_test.go b/internal/view/live_view_test.go
index d3771bdc..7ea74f7f 100644
--- a/internal/view/live_view_test.go
+++ b/internal/view/live_view_test.go
@@ -20,7 +20,7 @@ apiVersion: v1
the secret name you want to quote to use tls.","title":"secretName","type":"string"}},"required":["http","class","classInSpec"],"type":"object"}
`
- v := NewLiveView(NewApp(mock.NewMockConfig()), "fred", nil)
+ v := NewLiveView(NewApp(mock.NewMockConfig(t)), "fred", nil)
require.NoError(t, v.Init(context.Background()))
v.text.SetText(colorizeYAML(config.Yaml{}, s))
diff --git a/internal/view/log_int_test.go b/internal/view/log_int_test.go
index 64b3ae22..9630416c 100644
--- a/internal/view/log_int_test.go
+++ b/internal/view/log_int_test.go
@@ -21,7 +21,7 @@ func TestLogAutoScroll(t *testing.T) {
SingleContainer: true,
}
v := NewLog(client.PodGVR, &opts)
- require.NoError(t, v.Init(makeContext()))
+ require.NoError(t, v.Init(makeContext(t)))
ii := dao.NewLogItems()
ii.Add(dao.NewLogItemFromString("blee"), dao.NewLogItemFromString("bozo"))
v.GetModel().Set(ii)
@@ -39,7 +39,7 @@ func TestLogViewNav(t *testing.T) {
Container: "blee",
}
v := NewLog(client.PodGVR, &opts)
- require.NoError(t, v.Init(makeContext()))
+ require.NoError(t, v.Init(makeContext(t)))
buff := dao.NewLogItems()
for i := range 100 {
@@ -58,7 +58,7 @@ func TestLogViewClear(t *testing.T) {
Container: "blee",
}
v := NewLog(client.PodGVR, &opts)
- require.NoError(t, v.Init(makeContext()))
+ require.NoError(t, v.Init(makeContext(t)))
v.toggleAutoScrollCmd(nil)
v.Logs().SetText("blee\nblah")
@@ -73,7 +73,7 @@ func TestLogTimestamp(t *testing.T) {
Container: "c1",
}
l := NewLog(client.NewGVR("test"), &opts)
- require.NoError(t, l.Init(makeContext()))
+ require.NoError(t, l.Init(makeContext(t)))
ii := dao.NewLogItems()
ii.Add(
&dao.LogItem{
@@ -103,7 +103,7 @@ func TestLogFilter(t *testing.T) {
Container: "c1",
}
l := NewLog(client.NewGVR("test"), &opts)
- require.NoError(t, l.Init(makeContext()))
+ require.NoError(t, l.Init(makeContext(t)))
buff := dao.NewLogItems()
buff.Add(
dao.NewLogItemFromString("duh"),
diff --git a/internal/view/log_test.go b/internal/view/log_test.go
index 0708960a..318396b0 100644
--- a/internal/view/log_test.go
+++ b/internal/view/log_test.go
@@ -28,7 +28,7 @@ func TestLog(t *testing.T) {
Container: "blee",
}
v := view.NewLog(client.PodGVR, &opts)
- require.NoError(t, v.Init(makeContext()))
+ require.NoError(t, v.Init(makeContext(t)))
ii := dao.NewLogItems()
ii.Add(dao.NewLogItemFromString("blee\n"), dao.NewLogItemFromString("bozo\n"))
@@ -45,7 +45,7 @@ func TestLogFlush(t *testing.T) {
Container: "blee",
}
v := view.NewLog(client.PodGVR, &opts)
- require.NoError(t, v.Init(makeContext()))
+ require.NoError(t, v.Init(makeContext(t)))
items := dao.NewLogItems()
items.Add(
@@ -65,7 +65,7 @@ func BenchmarkLogFlush(b *testing.B) {
Container: "blee",
}
v := view.NewLog(client.PodGVR, &opts)
- _ = v.Init(makeContext())
+ _ = v.Init(makeContext(b))
items := dao.NewLogItems()
items.Add(
@@ -103,9 +103,9 @@ func TestLogViewSave(t *testing.T) {
Container: "blee",
}
v := view.NewLog(client.PodGVR, &opts)
- require.NoError(t, v.Init(makeContext()))
+ require.NoError(t, v.Init(makeContext(t)))
- app := makeApp()
+ app := makeApp(t)
ii := dao.NewLogItems()
ii.Add(dao.NewLogItemFromString("blee"), dao.NewLogItemFromString("bozo"))
ll := make([][]byte, ii.Len())
@@ -141,7 +141,7 @@ func TestAllContainerKeyBinding(t *testing.T) {
u := uu[k]
t.Run(k, func(t *testing.T) {
v := view.NewLog(client.PodGVR, u.opts)
- require.NoError(t, v.Init(makeContext()))
+ require.NoError(t, v.Init(makeContext(t)))
_, got := v.Logs().Actions().Get(ui.KeyA)
assert.Equal(t, u.e, got)
})
@@ -151,8 +151,8 @@ func TestAllContainerKeyBinding(t *testing.T) {
// ----------------------------------------------------------------------------
// Helpers...
-func makeApp() *view.App {
- return view.NewApp(mock.NewMockConfig())
+func makeApp(t *testing.T) *view.App {
+ return view.NewApp(mock.NewMockConfig(t))
}
func ensureDumpDir(n string) error {
diff --git a/internal/view/ns.go b/internal/view/ns.go
index 6453176b..fb67feb8 100644
--- a/internal/view/ns.go
+++ b/internal/view/ns.go
@@ -41,7 +41,7 @@ func (n *Namespace) bindKeys(aa *ui.KeyActions) {
func (n *Namespace) switchNs(app *App, _ ui.Tabular, _ *client.GVR, path string) {
n.useNamespace(path)
- app.gotoResource("pods", "", false, true)
+ app.gotoResource(client.PodGVR.String(), "", false, true)
}
func (n *Namespace) useNsCmd(*tcell.EventKey) *tcell.EventKey {
diff --git a/internal/view/ns_test.go b/internal/view/ns_test.go
index 5ab3e281..3cd81374 100644
--- a/internal/view/ns_test.go
+++ b/internal/view/ns_test.go
@@ -15,7 +15,7 @@ import (
func TestNSCleanser(t *testing.T) {
ns := view.NewNamespace(client.NsGVR)
- require.NoError(t, ns.Init(makeCtx()))
+ require.NoError(t, ns.Init(makeCtx(t)))
assert.Equal(t, "Namespaces", ns.Name())
assert.Len(t, ns.Hints(), 7)
}
diff --git a/internal/view/pf_test.go b/internal/view/pf_test.go
index ef04b9e3..ebc030ce 100644
--- a/internal/view/pf_test.go
+++ b/internal/view/pf_test.go
@@ -15,7 +15,7 @@ import (
func TestPortForwardNew(t *testing.T) {
pf := view.NewPortForward(client.PfGVR)
- require.NoError(t, pf.Init(makeCtx()))
+ require.NoError(t, pf.Init(makeCtx(t)))
assert.Equal(t, "PortForwards", pf.Name())
assert.Len(t, pf.Hints(), 10)
}
diff --git a/internal/view/pod_test.go b/internal/view/pod_test.go
index c1aee845..fa637f7a 100644
--- a/internal/view/pod_test.go
+++ b/internal/view/pod_test.go
@@ -18,14 +18,14 @@ import (
func TestPodNew(t *testing.T) {
po := view.NewPod(client.PodGVR)
- require.NoError(t, po.Init(makeCtx()))
+ require.NoError(t, po.Init(makeCtx(t)))
assert.Equal(t, "Pods", po.Name())
assert.Len(t, po.Hints(), 28)
}
// Helpers...
-func makeCtx() context.Context {
- cfg := mock.NewMockConfig()
+func makeCtx(t testing.TB) context.Context {
+ cfg := mock.NewMockConfig(t)
return context.WithValue(context.Background(), internal.KeyApp, view.NewApp(cfg))
}
diff --git a/internal/view/priorityclass_test.go b/internal/view/priorityclass_test.go
index 0819ce67..b3e4f0ea 100644
--- a/internal/view/priorityclass_test.go
+++ b/internal/view/priorityclass_test.go
@@ -15,7 +15,7 @@ import (
func TestPriorityClassNew(t *testing.T) {
s := view.NewPriorityClass(client.PcGVR)
- require.NoError(t, s.Init(makeCtx()))
+ require.NoError(t, s.Init(makeCtx(t)))
assert.Equal(t, "PriorityClass", s.Name())
assert.Len(t, s.Hints(), 6)
}
diff --git a/internal/view/pvc_test.go b/internal/view/pvc_test.go
index bbd7112e..56723e96 100644
--- a/internal/view/pvc_test.go
+++ b/internal/view/pvc_test.go
@@ -15,7 +15,7 @@ import (
func TestPVCNew(t *testing.T) {
v := view.NewPersistentVolumeClaim(client.PvcGVR)
- require.NoError(t, v.Init(makeCtx()))
+ require.NoError(t, v.Init(makeCtx(t)))
assert.Equal(t, "PersistentVolumeClaims", v.Name())
assert.Len(t, v.Hints(), 11)
}
diff --git a/internal/view/rbac_test.go b/internal/view/rbac_test.go
index 169ec0c6..2ff06571 100644
--- a/internal/view/rbac_test.go
+++ b/internal/view/rbac_test.go
@@ -15,7 +15,7 @@ import (
func TestRbacNew(t *testing.T) {
v := view.NewRbac(client.RbacGVR)
- require.NoError(t, v.Init(makeCtx()))
+ require.NoError(t, v.Init(makeCtx(t)))
assert.Equal(t, "Rbac", v.Name())
assert.Len(t, v.Hints(), 5)
}
diff --git a/internal/view/reference.go b/internal/view/reference.go
index da248931..3bb7b450 100644
--- a/internal/view/reference.go
+++ b/internal/view/reference.go
@@ -56,7 +56,7 @@ func (r *Reference) gotoCmd(evt *tcell.EventKey) *tcell.EventKey {
path := r.GetTable().GetSelectedItem()
ns, _ := client.Namespaced(path)
gvr := ui.TrimCell(r.GetTable().SelectTable, row, 2)
- r.App().gotoResource(client.NewGVR(gvr).R()+" "+ns, path, false, true)
+ r.App().gotoResource(client.NewGVR(gvr).String()+" "+ns, path, false, true)
return evt
}
diff --git a/internal/view/reference_test.go b/internal/view/reference_test.go
index 359e0037..63188f73 100644
--- a/internal/view/reference_test.go
+++ b/internal/view/reference_test.go
@@ -15,7 +15,7 @@ import (
func TestReferenceNew(t *testing.T) {
s := view.NewReference(client.RefGVR)
- require.NoError(t, s.Init(makeCtx()))
+ require.NoError(t, s.Init(makeCtx(t)))
assert.Equal(t, "References", s.Name())
assert.Len(t, s.Hints(), 4)
}
diff --git a/internal/view/screen_dump_test.go b/internal/view/screen_dump_test.go
index 96af8bb2..06740fc6 100644
--- a/internal/view/screen_dump_test.go
+++ b/internal/view/screen_dump_test.go
@@ -15,7 +15,7 @@ import (
func TestScreenDumpNew(t *testing.T) {
po := view.NewScreenDump(client.SdGVR)
- require.NoError(t, po.Init(makeCtx()))
+ require.NoError(t, po.Init(makeCtx(t)))
assert.Equal(t, "ScreenDumps", po.Name())
assert.Len(t, po.Hints(), 5)
}
diff --git a/internal/view/secret_test.go b/internal/view/secret_test.go
index 7e28ab62..0b76e597 100644
--- a/internal/view/secret_test.go
+++ b/internal/view/secret_test.go
@@ -15,7 +15,7 @@ import (
func TestSecretNew(t *testing.T) {
s := view.NewSecret(client.SecGVR)
- require.NoError(t, s.Init(makeCtx()))
+ require.NoError(t, s.Init(makeCtx(t)))
assert.Equal(t, "Secrets", s.Name())
assert.Len(t, s.Hints(), 8)
}
diff --git a/internal/view/sts_test.go b/internal/view/sts_test.go
index 119e8d02..0ff5d12d 100644
--- a/internal/view/sts_test.go
+++ b/internal/view/sts_test.go
@@ -15,7 +15,7 @@ import (
func TestStatefulSetNew(t *testing.T) {
s := view.NewStatefulSet(client.StsGVR)
- require.NoError(t, s.Init(makeCtx()))
+ require.NoError(t, s.Init(makeCtx(t)))
assert.Equal(t, "StatefulSets", s.Name())
assert.Len(t, s.Hints(), 14)
}
diff --git a/internal/view/svc_test.go b/internal/view/svc_test.go
index 5e0f3ffc..3682fc56 100644
--- a/internal/view/svc_test.go
+++ b/internal/view/svc_test.go
@@ -172,7 +172,7 @@ func init() {
func TestServiceNew(t *testing.T) {
s := view.NewService(client.SvcGVR)
- require.NoError(t, s.Init(makeCtx()))
+ require.NoError(t, s.Init(makeCtx(t)))
assert.Equal(t, "Services", s.Name())
assert.Len(t, s.Hints(), 12)
}
diff --git a/internal/view/table_int_test.go b/internal/view/table_int_test.go
index 29966e89..5d2652e0 100644
--- a/internal/view/table_int_test.go
+++ b/internal/view/table_int_test.go
@@ -29,7 +29,7 @@ import (
func TestTableSave(t *testing.T) {
v := NewTable(client.NewGVR("test"))
- require.NoError(t, v.Init(makeContext()))
+ require.NoError(t, v.Init(makeContext(t)))
v.SetTitle("k9s-test")
require.NoError(t, ensureDumpDir("/tmp/test-dumps"))
@@ -43,7 +43,7 @@ func TestTableSave(t *testing.T) {
func TestTableNew(t *testing.T) {
v := NewTable(client.NewGVR("test"))
- require.NoError(t, v.Init(makeContext()))
+ require.NoError(t, v.Init(makeContext(t)))
data := model1.NewTableDataWithRows(
client.NewGVR("test"),
@@ -74,7 +74,7 @@ func TestTableNew(t *testing.T) {
func TestTableViewFilter(t *testing.T) {
v := NewTable(client.NewGVR("test"))
- require.NoError(t, v.Init(makeContext()))
+ require.NoError(t, v.Init(makeContext(t)))
v.SetModel(&mockTableModel{})
v.Refresh()
@@ -86,7 +86,7 @@ func TestTableViewFilter(t *testing.T) {
func TestTableViewSort(t *testing.T) {
v := NewTable(client.NewGVR("test"))
- require.NoError(t, v.Init(makeContext()))
+ require.NoError(t, v.Init(makeContext(t)))
v.SetModel(new(mockTableModel))
uu := map[string]struct {
@@ -199,8 +199,8 @@ func makeTableData() *model1.TableData {
)
}
-func makeContext() context.Context {
- a := NewApp(mock.NewMockConfig())
+func makeContext(t *testing.T) context.Context {
+ a := NewApp(mock.NewMockConfig(t))
ctx := context.WithValue(context.Background(), internal.KeyApp, a)
return context.WithValue(ctx, internal.KeyStyles, a.Styles)
}
diff --git a/internal/view/workload.go b/internal/view/workload.go
index 72aaf727..c4f6479f 100644
--- a/internal/view/workload.go
+++ b/internal/view/workload.go
@@ -83,7 +83,7 @@ func (*Workload) showRes(app *App, _ ui.Tabular, _ *client.GVR, path string) {
app.Flash().Err(fmt.Errorf("unable to parse path: %q", path))
return
}
- app.gotoResource(gvr.R(), fqn, false, true)
+ app.gotoResource(gvr.String(), fqn, false, true)
}
func (w *Workload) deleteCmd(evt *tcell.EventKey) *tcell.EventKey {
diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml
index 00174b88..2dff457e 100644
--- a/snap/snapcraft.yaml
+++ b/snap/snapcraft.yaml
@@ -1,6 +1,6 @@
name: k9s
base: core22
-version: 'v0.50.0'
+version: 'v0.50.1'
summary: K9s is a CLI to view and manage your Kubernetes clusters.
description: |
K9s is a CLI to view and manage your Kubernetes clusters. By leveraging a terminal UI, you can easily traverse Kubernetes resources and view the state of your clusters in a single powerful session.