parent
e55083ba27
commit
142282b584
2
Makefile
2
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}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
<img src="https://raw.githubusercontent.com/derailed/k9s/master/assets/k9s.png" align="center" width="800" height="auto"/>
|
||||
|
||||
# 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
|
||||
|
||||
|
||||
---
|
||||
<img src="https://raw.githubusercontent.com/derailed/k9s/master/assets/imhotep_logo.png" width="32" height="auto"/> © 2025 Imhotep Software LLC. All materials licensed under [Apache v2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
||||
|
|
@ -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, "/")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -386,7 +386,9 @@ func (k *K9s) Validate(c client.Connection, contextName, clusterName string) {
|
|||
if k.getActiveConfig() == nil {
|
||||
_, _ = k.ActivateContext(contextName)
|
||||
}
|
||||
if k.ShellPod != nil {
|
||||
k.ShellPod.Validate()
|
||||
}
|
||||
k.Logger = k.Logger.Validate()
|
||||
k.Thresholds = k.Thresholds.Validate()
|
||||
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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...)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -157,23 +148,10 @@ 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)
|
||||
}
|
||||
|
||||
dt := pwm.Raw.GetDeletionTimestamp()
|
||||
_, _, irc, _ := p.Statuses(st.InitContainerStatuses)
|
||||
|
|
|
|||
|
|
@ -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"}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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] <Blee> \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] <Blee> \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] <Blee> \n", i.GetText(false))
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 == ""
|
||||
|
|
|
|||
|
|
@ -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{
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
||||
|
|
|
|||
|
|
@ -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"),
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Reference in New Issue