diff --git a/Makefile b/Makefile
index 35cb6f91..48fb6e72 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
NAME := k9s
-VERSION ?= v0.50.13
+VERSION ?= v0.50.14
PACKAGE := github.com/derailed/$(NAME)
OUTPUT_BIN ?= execs/${NAME}
GO_FLAGS ?=
diff --git a/change_logs/release_v0.50.14.md b/change_logs/release_v0.50.14.md
new file mode 100644
index 00000000..a6c8e104
--- /dev/null
+++ b/change_logs/release_v0.50.14.md
@@ -0,0 +1,35 @@
+
+
+# Release v0.50.14
+
+## 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 big corporations with deep pockets, thus if you feel K9s is helping in 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/zt-3360a389v-ElLHrb0Dp1kAXqYUItSAFA)
+
+## Maintenance Release!
+
+Sponsorships are dropping at an alarming rate which puts this project in the red. This is becoming a concern and sad not to mention unsustainable ;( If you dig `k9s` and want to help the project, please consider `paying it forward!` and don't become just another `satisfied, non paying customer!`. K9s does take a lot of my `free` time to maintain, enhance and keep the light on. Many cool ideas are making it straight to the `freezer` as I just can't budget them in.
+I know many of you work for big corporations, so please put in the word/work and have them help us out via sponsorships or other means.
+
+Thank you!
+
+## Resolved Issues
+
+* [#3608](https://github.com/derailed/k9s/issues/3608) k9s crashes when :namespaces used
+* [#3606](https://github.com/derailed/k9s/issues/3606) Xray not working anymore on (possible) v0.50.X
+* [#3594](https://github.com/derailed/k9s/issues/3594) Show pod yaml - Boom!! cannot deep copy int
+* [#3591](https://github.com/derailed/k9s/issues/3591) Accept suggestion with enter (without having to "tab")
+* [#3576](https://github.com/derailed/k9s/issues/3576) Custom alias/view not working anymore since v0.50.10
+
+---
+
© 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/config/alias.go b/internal/config/alias.go
index 60c2d3f1..bb64c3b6 100644
--- a/internal/config/alias.go
+++ b/internal/config/alias.go
@@ -89,7 +89,7 @@ func (a *Aliases) Resolve(p *cmd.Interpreter) (*client.GVR, bool) {
}
if gvr.IsK8sRes() {
- p.Reset(strings.Replace(p.GetLine(), p.Cmd(), gvr.String(), 1))
+ p.Reset(strings.Replace(p.GetLine(), p.Cmd(), gvr.String(), 1), gvr.String())
return gvr, true
}
@@ -100,7 +100,7 @@ func (a *Aliases) Resolve(p *cmd.Interpreter) (*client.GVR, bool) {
return gvr, false
}
ap.Merge(p)
- p.Reset(strings.Replace(ap.GetLine(), ap.Cmd(), gvr.String(), 1))
+ p.Reset(strings.Replace(ap.GetLine(), ap.Cmd(), gvr.String(), 1), ap.Cmd())
}
return gvr, true
diff --git a/internal/dao/helpers.go b/internal/dao/helpers.go
index dcee0f46..fa3c0eb9 100644
--- a/internal/dao/helpers.go
+++ b/internal/dao/helpers.go
@@ -86,16 +86,11 @@ func ToYAML(o runtime.Object, showManaged bool) (string, error) {
if o == nil {
return "", errors.New("no object to yamlize")
}
- u, ok := o.(*unstructured.Unstructured)
- if !ok {
- return "", fmt.Errorf("expecting unstructured but got %T", o)
- }
- if u.Object == nil {
- return "", fmt.Errorf("expecting unstructured object but got nil")
- }
var p printers.ResourcePrinter = &printers.YAMLPrinter{}
+
if !showManaged {
+ o = o.DeepCopyObject()
p = &printers.OmitManagedFieldsPrinter{Delegate: p}
}
diff --git a/internal/ui/app.go b/internal/ui/app.go
index a1f21b7b..686dafc0 100644
--- a/internal/ui/app.go
+++ b/internal/ui/app.go
@@ -190,6 +190,9 @@ func (a *App) ActivateCmd(b bool) {
// GetCmd retrieves user command.
func (a *App) GetCmd() string {
+ if sugs := a.cmdBuff.Suggestions(); len(sugs) >= 1 {
+ return a.cmdBuff.GetText() + sugs[0]
+ }
return a.cmdBuff.GetText()
}
diff --git a/internal/view/app.go b/internal/view/app.go
index 1d850788..c3c9c1b4 100644
--- a/internal/view/app.go
+++ b/internal/view/app.go
@@ -626,8 +626,9 @@ func (a *App) toggleCrumbsCmd(evt *tcell.EventKey) *tcell.EventKey {
}
func (a *App) gotoCmd(evt *tcell.EventKey) *tcell.EventKey {
- if a.CmdBuff().IsActive() && !a.CmdBuff().Empty() {
- a.gotoResource(a.GetCmd(), "", true, true)
+ c := a.GetCmd()
+ if a.CmdBuff().IsActive() && c != "" {
+ a.gotoResource(c, "", true, true)
a.ResetCmd()
return nil
}
diff --git a/internal/view/cmd/interpreter.go b/internal/view/cmd/interpreter.go
index d0951043..a15087d7 100644
--- a/internal/view/cmd/interpreter.go
+++ b/internal/view/cmd/interpreter.go
@@ -14,16 +14,18 @@ import (
// Interpreter tracks user prompt input.
type Interpreter struct {
- line string
- cmd string
- args args
+ line string
+ cmd string
+ aliases []string
+ args args
}
// NewInterpreter returns a new instance.
-func NewInterpreter(s string) *Interpreter {
+func NewInterpreter(s string, aliases ...string) *Interpreter {
c := Interpreter{
- line: s,
- args: make(args),
+ line: s,
+ args: make(args),
+ aliases: aliases,
}
c.grok()
@@ -38,11 +40,11 @@ func (c *Interpreter) ClearNS() {
// SwitchNS replaces the current namespace with the provided one.
func (c *Interpreter) SwitchNS(ns string) {
if ons, ok := c.NSArg(); ok && ons != client.BlankNamespace {
- c.Reset(strings.TrimSpace(strings.Replace(c.line, " "+ons, " "+ns, 1)))
+ c.Reset(strings.TrimSpace(strings.Replace(c.line, " "+ons, " "+ns, 1)), "")
return
}
if ns != client.BlankNamespace {
- c.Reset(strings.TrimSpace(c.line) + " " + ns)
+ c.Reset(strings.TrimSpace(c.line)+" "+ns, "")
}
}
@@ -111,6 +113,10 @@ func (c *Interpreter) Cmd() string {
return c.cmd
}
+func (c *Interpreter) Aliases() []string {
+ return c.aliases
+}
+
func (c *Interpreter) Args() string {
return strings.TrimSpace(strings.Replace(c.line, c.cmd, "", 1))
}
@@ -134,13 +140,26 @@ func (c *Interpreter) Amend(c1 *Interpreter) {
}
// Reset resets with new command.
-func (c *Interpreter) Reset(s string) *Interpreter {
- c.line = s
+func (c *Interpreter) Reset(line, alias string) *Interpreter {
+ c.line = line
c.grok()
+ if alias != "" && alias != c.cmd {
+ c.addAlias(alias)
+ }
+
return c
}
+func (c *Interpreter) addAlias(a string) {
+ for _, v := range c.aliases {
+ if v == a {
+ return
+ }
+ }
+ c.aliases = append(c.aliases, a)
+}
+
// GetLine returns the prompt.
func (c *Interpreter) GetLine() string {
return strings.TrimSpace(c.line)
diff --git a/internal/view/command.go b/internal/view/command.go
index bfe44d9d..6898b728 100644
--- a/internal/view/command.go
+++ b/internal/view/command.go
@@ -118,7 +118,7 @@ func (*Command) namespaceCmd(p *cmd.Interpreter) bool {
}
if ns != "" {
- _ = p.Reset(client.PodGVR.String())
+ _ = p.Reset(client.PodGVR.String(), "")
p.SwitchNS(ns)
}
@@ -139,7 +139,7 @@ func (c *Command) xrayCmd(p *cmd.Interpreter, pushCmd bool) error {
if !ok {
return errors.New("invalid command. use `xray xxx`")
}
- gvr, ok := c.alias.Resolve(p)
+ gvr, ok := c.alias.Resolve(cmd.NewInterpreter(arg))
if !ok {
return fmt.Errorf("invalid resource name: %q", arg)
}
@@ -240,7 +240,7 @@ func (c *Command) defaultCmd(isRoot bool) error {
}
p := cmd.NewInterpreter(c.app.Config.ActiveView())
if p.IsBlank() {
- return c.run(p.Reset(defCmd), "", true, true)
+ return c.run(p.Reset(defCmd, ""), "", true, true)
}
if err := c.run(p, "", true, true); err != nil {
@@ -248,7 +248,7 @@ func (c *Command) defaultCmd(isRoot bool) error {
slogs.Command, p.GetLine(),
slogs.Error, err,
)
- p = p.Reset(defCmd)
+ p = p.Reset(defCmd, "")
return c.run(p, "", true, true)
}
@@ -345,7 +345,7 @@ func (c *Command) exec(p *cmd.Interpreter, gvr *client.GVR, comp model.Component
ci := cmd.NewInterpreter(podCmd)
currentCommand, ok := c.app.cmdHistory.Top()
if ok {
- ci = ci.Reset(currentCommand)
+ ci = ci.Reset(currentCommand, "")
}
err = c.run(ci, "", true, true)
}
diff --git a/internal/view/command_test.go b/internal/view/command_test.go
index b497859d..8bd9c4d4 100644
--- a/internal/view/command_test.go
+++ b/internal/view/command_test.go
@@ -47,14 +47,14 @@ func Test_viewMetaFor(t *testing.T) {
"custom-alias": {
cmd: "pdl",
gvr: client.PodGVR,
- p: cmd.NewInterpreter("v1/pods @fred 'app=blee' default"),
+ p: cmd.NewInterpreter("v1/pods @fred 'app=blee' default", "pdl"),
err: errors.New("blee"),
},
"inception": {
cmd: "pdal blee",
gvr: client.PodGVR,
- p: cmd.NewInterpreter("v1/pods @fred 'app=blee' blee"),
+ p: cmd.NewInterpreter("v1/pods @fred 'app=blee' blee", "pdal", "pod"),
err: errors.New("blee"),
},
}
diff --git a/internal/view/live_view.go b/internal/view/live_view.go
index 8a738fb4..e8d9bee3 100644
--- a/internal/view/live_view.go
+++ b/internal/view/live_view.go
@@ -276,6 +276,7 @@ func (v *LiveView) toggleManagedCmd(evt *tcell.EventKey) *tcell.EventKey {
v.managedField = !v.managedField
v.model.SetOptions(v.defaultCtx(), map[string]bool{model.ManagedFieldsOpts: v.managedField})
+ v.app.Flash().Info("toggled managed fields")
return nil
}
diff --git a/internal/view/table.go b/internal/view/table.go
index 9e89a961..f05c4780 100644
--- a/internal/view/table.go
+++ b/internal/view/table.go
@@ -149,7 +149,12 @@ func (t *Table) Start() {
t.Styles().AddListener(t.Table)
cmds := []string{t.Table.GVR().String()}
if t.command != nil {
- cmds = append(cmds, t.command.GetLine())
+ if t.command.GetLine() != t.Table.GVR().String() {
+ cmds = append(cmds, t.command.GetLine())
+ }
+ for _, a := range t.command.Aliases() {
+ cmds = append(cmds, a)
+ }
}
t.App().CustomView().AddListeners(t.Table, cmds...)
}
diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml
index 2c091639..023baa04 100644
--- a/snap/snapcraft.yaml
+++ b/snap/snapcraft.yaml
@@ -1,6 +1,6 @@
name: k9s
base: core22
-version: 'v0.50.13'
+version: 'v0.50.14'
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.