Rel v0.50.14 (#3609)

* fix #3591 #3608 suggestions enter accept

* fix#3606-xray busted

* fix#3594-yaml busted

* rel notes
mine
Fernand Galiana 2025-10-06 17:57:12 -06:00 committed by GitHub
parent 41acad343b
commit 73fa008736
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 90 additions and 31 deletions

View File

@ -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 ?=

View File

@ -0,0 +1,35 @@
<img src="https://raw.githubusercontent.com/derailed/k9s/master/assets/k9s.png" align="center" width="800" height="auto"/>
# 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
---
<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)#

View File

@ -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

View File

@ -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}
}

View File

@ -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()
}

View File

@ -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
}

View File

@ -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)

View File

@ -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)
}

View File

@ -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"),
},
}

View File

@ -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
}

View File

@ -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...)
}

View File

@ -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.