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.