Rel v0.50.14 (#3609)
* fix #3591 #3608 suggestions enter accept * fix#3606-xray busted * fix#3594-yaml busted * rel notesmine
parent
41acad343b
commit
73fa008736
2
Makefile
2
Makefile
|
|
@ -1,5 +1,5 @@
|
||||||
NAME := k9s
|
NAME := k9s
|
||||||
VERSION ?= v0.50.13
|
VERSION ?= v0.50.14
|
||||||
PACKAGE := github.com/derailed/$(NAME)
|
PACKAGE := github.com/derailed/$(NAME)
|
||||||
OUTPUT_BIN ?= execs/${NAME}
|
OUTPUT_BIN ?= execs/${NAME}
|
||||||
GO_FLAGS ?=
|
GO_FLAGS ?=
|
||||||
|
|
|
||||||
|
|
@ -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)#
|
||||||
|
|
@ -89,7 +89,7 @@ func (a *Aliases) Resolve(p *cmd.Interpreter) (*client.GVR, bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if gvr.IsK8sRes() {
|
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
|
return gvr, true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -100,7 +100,7 @@ func (a *Aliases) Resolve(p *cmd.Interpreter) (*client.GVR, bool) {
|
||||||
return gvr, false
|
return gvr, false
|
||||||
}
|
}
|
||||||
ap.Merge(p)
|
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
|
return gvr, true
|
||||||
|
|
|
||||||
|
|
@ -86,16 +86,11 @@ func ToYAML(o runtime.Object, showManaged bool) (string, error) {
|
||||||
if o == nil {
|
if o == nil {
|
||||||
return "", errors.New("no object to yamlize")
|
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{}
|
var p printers.ResourcePrinter = &printers.YAMLPrinter{}
|
||||||
|
|
||||||
if !showManaged {
|
if !showManaged {
|
||||||
|
o = o.DeepCopyObject()
|
||||||
p = &printers.OmitManagedFieldsPrinter{Delegate: p}
|
p = &printers.OmitManagedFieldsPrinter{Delegate: p}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -190,6 +190,9 @@ func (a *App) ActivateCmd(b bool) {
|
||||||
|
|
||||||
// GetCmd retrieves user command.
|
// GetCmd retrieves user command.
|
||||||
func (a *App) GetCmd() string {
|
func (a *App) GetCmd() string {
|
||||||
|
if sugs := a.cmdBuff.Suggestions(); len(sugs) >= 1 {
|
||||||
|
return a.cmdBuff.GetText() + sugs[0]
|
||||||
|
}
|
||||||
return a.cmdBuff.GetText()
|
return a.cmdBuff.GetText()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -626,8 +626,9 @@ func (a *App) toggleCrumbsCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) gotoCmd(evt *tcell.EventKey) *tcell.EventKey {
|
func (a *App) gotoCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
if a.CmdBuff().IsActive() && !a.CmdBuff().Empty() {
|
c := a.GetCmd()
|
||||||
a.gotoResource(a.GetCmd(), "", true, true)
|
if a.CmdBuff().IsActive() && c != "" {
|
||||||
|
a.gotoResource(c, "", true, true)
|
||||||
a.ResetCmd()
|
a.ResetCmd()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,16 +14,18 @@ import (
|
||||||
|
|
||||||
// Interpreter tracks user prompt input.
|
// Interpreter tracks user prompt input.
|
||||||
type Interpreter struct {
|
type Interpreter struct {
|
||||||
line string
|
line string
|
||||||
cmd string
|
cmd string
|
||||||
args args
|
aliases []string
|
||||||
|
args args
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewInterpreter returns a new instance.
|
// NewInterpreter returns a new instance.
|
||||||
func NewInterpreter(s string) *Interpreter {
|
func NewInterpreter(s string, aliases ...string) *Interpreter {
|
||||||
c := Interpreter{
|
c := Interpreter{
|
||||||
line: s,
|
line: s,
|
||||||
args: make(args),
|
args: make(args),
|
||||||
|
aliases: aliases,
|
||||||
}
|
}
|
||||||
c.grok()
|
c.grok()
|
||||||
|
|
||||||
|
|
@ -38,11 +40,11 @@ func (c *Interpreter) ClearNS() {
|
||||||
// SwitchNS replaces the current namespace with the provided one.
|
// SwitchNS replaces the current namespace with the provided one.
|
||||||
func (c *Interpreter) SwitchNS(ns string) {
|
func (c *Interpreter) SwitchNS(ns string) {
|
||||||
if ons, ok := c.NSArg(); ok && ons != client.BlankNamespace {
|
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
|
return
|
||||||
}
|
}
|
||||||
if ns != client.BlankNamespace {
|
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
|
return c.cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Interpreter) Aliases() []string {
|
||||||
|
return c.aliases
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Interpreter) Args() string {
|
func (c *Interpreter) Args() string {
|
||||||
return strings.TrimSpace(strings.Replace(c.line, c.cmd, "", 1))
|
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.
|
// Reset resets with new command.
|
||||||
func (c *Interpreter) Reset(s string) *Interpreter {
|
func (c *Interpreter) Reset(line, alias string) *Interpreter {
|
||||||
c.line = s
|
c.line = line
|
||||||
c.grok()
|
c.grok()
|
||||||
|
|
||||||
|
if alias != "" && alias != c.cmd {
|
||||||
|
c.addAlias(alias)
|
||||||
|
}
|
||||||
|
|
||||||
return c
|
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.
|
// GetLine returns the prompt.
|
||||||
func (c *Interpreter) GetLine() string {
|
func (c *Interpreter) GetLine() string {
|
||||||
return strings.TrimSpace(c.line)
|
return strings.TrimSpace(c.line)
|
||||||
|
|
|
||||||
|
|
@ -118,7 +118,7 @@ func (*Command) namespaceCmd(p *cmd.Interpreter) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ns != "" {
|
if ns != "" {
|
||||||
_ = p.Reset(client.PodGVR.String())
|
_ = p.Reset(client.PodGVR.String(), "")
|
||||||
p.SwitchNS(ns)
|
p.SwitchNS(ns)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -139,7 +139,7 @@ func (c *Command) xrayCmd(p *cmd.Interpreter, pushCmd bool) error {
|
||||||
if !ok {
|
if !ok {
|
||||||
return errors.New("invalid command. use `xray xxx`")
|
return errors.New("invalid command. use `xray xxx`")
|
||||||
}
|
}
|
||||||
gvr, ok := c.alias.Resolve(p)
|
gvr, ok := c.alias.Resolve(cmd.NewInterpreter(arg))
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("invalid resource name: %q", arg)
|
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())
|
p := cmd.NewInterpreter(c.app.Config.ActiveView())
|
||||||
if p.IsBlank() {
|
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 {
|
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.Command, p.GetLine(),
|
||||||
slogs.Error, err,
|
slogs.Error, err,
|
||||||
)
|
)
|
||||||
p = p.Reset(defCmd)
|
p = p.Reset(defCmd, "")
|
||||||
return c.run(p, "", true, true)
|
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)
|
ci := cmd.NewInterpreter(podCmd)
|
||||||
currentCommand, ok := c.app.cmdHistory.Top()
|
currentCommand, ok := c.app.cmdHistory.Top()
|
||||||
if ok {
|
if ok {
|
||||||
ci = ci.Reset(currentCommand)
|
ci = ci.Reset(currentCommand, "")
|
||||||
}
|
}
|
||||||
err = c.run(ci, "", true, true)
|
err = c.run(ci, "", true, true)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,14 +47,14 @@ func Test_viewMetaFor(t *testing.T) {
|
||||||
"custom-alias": {
|
"custom-alias": {
|
||||||
cmd: "pdl",
|
cmd: "pdl",
|
||||||
gvr: client.PodGVR,
|
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"),
|
err: errors.New("blee"),
|
||||||
},
|
},
|
||||||
|
|
||||||
"inception": {
|
"inception": {
|
||||||
cmd: "pdal blee",
|
cmd: "pdal blee",
|
||||||
gvr: client.PodGVR,
|
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"),
|
err: errors.New("blee"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -276,6 +276,7 @@ func (v *LiveView) toggleManagedCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
v.managedField = !v.managedField
|
v.managedField = !v.managedField
|
||||||
v.model.SetOptions(v.defaultCtx(), map[string]bool{model.ManagedFieldsOpts: v.managedField})
|
v.model.SetOptions(v.defaultCtx(), map[string]bool{model.ManagedFieldsOpts: v.managedField})
|
||||||
|
|
||||||
|
v.app.Flash().Info("toggled managed fields")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -149,7 +149,12 @@ func (t *Table) Start() {
|
||||||
t.Styles().AddListener(t.Table)
|
t.Styles().AddListener(t.Table)
|
||||||
cmds := []string{t.Table.GVR().String()}
|
cmds := []string{t.Table.GVR().String()}
|
||||||
if t.command != nil {
|
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...)
|
t.App().CustomView().AddListeners(t.Table, cmds...)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
name: k9s
|
name: k9s
|
||||||
base: core22
|
base: core22
|
||||||
version: 'v0.50.13'
|
version: 'v0.50.14'
|
||||||
summary: K9s is a CLI to view and manage your Kubernetes clusters.
|
summary: K9s is a CLI to view and manage your Kubernetes clusters.
|
||||||
description: |
|
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.
|
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