parent
4f5c1a1105
commit
5c5fcba6d8
2
Makefile
2
Makefile
|
|
@ -1,5 +1,5 @@
|
||||||
NAME := k9s
|
NAME := k9s
|
||||||
VERSION ?= v0.50.10
|
VERSION ?= v0.50.11
|
||||||
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,30 @@
|
||||||
|
<img src="https://raw.githubusercontent.com/derailed/k9s/master/assets/k9s.png" align="center" width="800" height="auto"/>
|
||||||
|
|
||||||
|
# Release v0.50.11
|
||||||
|
|
||||||
|
## 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/zt-3360a389v-ElLHrb0Dp1kAXqYUItSAFA)
|
||||||
|
|
||||||
|
## Maintenance Release!
|
||||||
|
|
||||||
|
Oh dear! Hopefully we're happier on this drop?? Apologizes for the `disturbance in the farce`...
|
||||||
|
|
||||||
|
## Resolved Issues
|
||||||
|
|
||||||
|
* [#3567](https://github.com/derailed/k9s/issues/3567) Extra slash '/' added when filtering from the command prompt
|
||||||
|
* [#3566](https://github.com/derailed/k9s/issues/3566) unable to switch context or use k9s after upgrade to 0.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)#
|
||||||
|
|
@ -88,7 +88,7 @@ func (g *GVR) IsCommand() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GVR) IsK8sRes() bool {
|
func (g *GVR) IsK8sRes() bool {
|
||||||
return g != nil && (strings.Contains(g.raw, "/") || reservedGVRs.Has(g))
|
return g != nil && ((strings.Contains(g.raw, "/") && !strings.Contains(g.raw, " /")) || reservedGVRs.Has(g))
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithSubResource builds a new gvr with a sub resource.
|
// WithSubResource builds a new gvr with a sub resource.
|
||||||
|
|
|
||||||
|
|
@ -201,14 +201,14 @@ func TestAliasResolve(t *testing.T) {
|
||||||
exp: "ppo",
|
exp: "ppo",
|
||||||
ok: true,
|
ok: true,
|
||||||
gvr: client.PodGVR,
|
gvr: client.PodGVR,
|
||||||
cmd: cmd.NewInterpreter("v1/pods a=b,b=c default"),
|
cmd: cmd.NewInterpreter("v1/pods 'a=b,b=c' default"),
|
||||||
},
|
},
|
||||||
|
|
||||||
"full-alias": {
|
"full-alias": {
|
||||||
exp: "ppc",
|
exp: "ppc",
|
||||||
ok: true,
|
ok: true,
|
||||||
gvr: client.PodGVR,
|
gvr: client.PodGVR,
|
||||||
cmd: cmd.NewInterpreter("v1/pods @fred app=fred default"),
|
cmd: cmd.NewInterpreter("v1/pods @fred 'app=fred' default"),
|
||||||
},
|
},
|
||||||
|
|
||||||
"plain-filter": {
|
"plain-filter": {
|
||||||
|
|
@ -229,7 +229,21 @@ func TestAliasResolve(t *testing.T) {
|
||||||
exp: "ppc /fred @bozo ns-1",
|
exp: "ppc /fred @bozo ns-1",
|
||||||
ok: true,
|
ok: true,
|
||||||
gvr: client.PodGVR,
|
gvr: client.PodGVR,
|
||||||
cmd: cmd.NewInterpreter("v1/pods @bozo /fred app=fred ns-1"),
|
cmd: cmd.NewInterpreter("v1/pods @bozo /fred 'app=fred' ns-1"),
|
||||||
|
},
|
||||||
|
|
||||||
|
"filtered": {
|
||||||
|
exp: "pc",
|
||||||
|
ok: true,
|
||||||
|
gvr: client.PodGVR,
|
||||||
|
cmd: cmd.NewInterpreter("v1/pods /cilium kube-system"),
|
||||||
|
},
|
||||||
|
|
||||||
|
"labels-in": {
|
||||||
|
exp: "ppp",
|
||||||
|
ok: true,
|
||||||
|
gvr: client.PodGVR,
|
||||||
|
cmd: cmd.NewInterpreter("v1/pods 'app in (be,fe)'"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -241,6 +255,8 @@ func TestAliasResolve(t *testing.T) {
|
||||||
a.Define(client.NewGVR("pod default"), "pp")
|
a.Define(client.NewGVR("pod default"), "pp")
|
||||||
a.Define(client.NewGVR("pipo a=b,b=c default"), "ppo")
|
a.Define(client.NewGVR("pipo a=b,b=c default"), "ppo")
|
||||||
a.Define(client.NewGVR("pod default app=fred @fred"), "ppc")
|
a.Define(client.NewGVR("pod default app=fred @fred"), "ppc")
|
||||||
|
a.Define(client.NewGVR("pod /cilium kube-system"), "pc")
|
||||||
|
a.Define(client.NewGVR("pod 'app in (be,fe)'"), "ppp")
|
||||||
for k := range uu {
|
for k := range uu {
|
||||||
u := uu[k]
|
u := uu[k]
|
||||||
t.Run(k, func(t *testing.T) {
|
t.Run(k, func(t *testing.T) {
|
||||||
|
|
|
||||||
|
|
@ -48,12 +48,12 @@ func newArgs(p *Interpreter, aa []string) args {
|
||||||
arguments[filterKey] = strings.ToLower(a[1:])
|
arguments[filterKey] = strings.ToLower(a[1:])
|
||||||
}
|
}
|
||||||
|
|
||||||
case isLabelArg(a):
|
|
||||||
arguments[labelKey] = strings.ToLower(a)
|
|
||||||
|
|
||||||
case strings.Index(a, contextFlag) == 0:
|
case strings.Index(a, contextFlag) == 0:
|
||||||
arguments[contextKey] = a[1:]
|
arguments[contextKey] = a[1:]
|
||||||
|
|
||||||
|
case isLabelArg(a):
|
||||||
|
arguments[labelKey] = strings.ToLower(a)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
switch {
|
switch {
|
||||||
case p.IsContextCmd():
|
case p.IsContextCmd():
|
||||||
|
|
@ -86,6 +86,8 @@ func (a args) String() string {
|
||||||
for _, k := range slices.Sorted(kk) {
|
for _, k := range slices.Sorted(kk) {
|
||||||
v := a[k]
|
v := a[k]
|
||||||
switch k {
|
switch k {
|
||||||
|
case labelKey:
|
||||||
|
v = "'" + v + "'"
|
||||||
case filterKey:
|
case filterKey:
|
||||||
v = filterFlag + v
|
v = filterFlag + v
|
||||||
case contextKey:
|
case contextKey:
|
||||||
|
|
|
||||||
|
|
@ -52,9 +52,7 @@ func (c *Interpreter) Merge(p *Interpreter) {
|
||||||
}
|
}
|
||||||
c.cmd = p.cmd
|
c.cmd = p.cmd
|
||||||
for k, v := range p.args {
|
for k, v := range p.args {
|
||||||
// if _, ok := c.args[k]; !ok {
|
|
||||||
c.args[k] = v
|
c.args[k] = v
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
c.line = c.cmd + " " + c.args.String()
|
c.line = c.cmd + " " + c.args.String()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -177,31 +177,42 @@ func TestFilterCmd(t *testing.T) {
|
||||||
filter string
|
filter string
|
||||||
}{
|
}{
|
||||||
"empty": {},
|
"empty": {},
|
||||||
|
|
||||||
"normal": {
|
"normal": {
|
||||||
cmd: "pod /fred",
|
cmd: "pod /fred",
|
||||||
ok: true,
|
ok: true,
|
||||||
filter: "fred",
|
filter: "fred",
|
||||||
},
|
},
|
||||||
|
|
||||||
"caps": {
|
"caps": {
|
||||||
cmd: "POD /FRED",
|
cmd: "POD /FRED",
|
||||||
ok: true,
|
ok: true,
|
||||||
filter: "fred",
|
filter: "fred",
|
||||||
},
|
},
|
||||||
|
|
||||||
"filter+ns": {
|
"filter+ns": {
|
||||||
cmd: "pod /fred ns1",
|
cmd: "pod /fred ns1",
|
||||||
ok: true,
|
ok: true,
|
||||||
filter: "fred",
|
filter: "fred",
|
||||||
},
|
},
|
||||||
|
|
||||||
"ns+filter": {
|
"ns+filter": {
|
||||||
cmd: "pod ns1 /fred",
|
cmd: "pod ns1 /fred",
|
||||||
ok: true,
|
ok: true,
|
||||||
filter: "fred",
|
filter: "fred",
|
||||||
},
|
},
|
||||||
|
|
||||||
"ns+filter+labels": {
|
"ns+filter+labels": {
|
||||||
cmd: "pod ns1 /fred app=blee,fred=zorg",
|
cmd: "pod ns1 /fred app=blee,fred=zorg",
|
||||||
ok: true,
|
ok: true,
|
||||||
filter: "fred",
|
filter: "fred",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"filtered": {
|
||||||
|
cmd: "pod /cilium kube-system",
|
||||||
|
ok: true,
|
||||||
|
filter: "cilium",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for k := range uu {
|
for k := range uu {
|
||||||
|
|
@ -431,24 +442,34 @@ func TestContextCmd(t *testing.T) {
|
||||||
ctx string
|
ctx string
|
||||||
}{
|
}{
|
||||||
"empty": {},
|
"empty": {},
|
||||||
|
|
||||||
"happy-full": {
|
"happy-full": {
|
||||||
cmd: "context ctx1",
|
cmd: "context ctx1",
|
||||||
ok: true,
|
ok: true,
|
||||||
ctx: "ctx1",
|
ctx: "ctx1",
|
||||||
},
|
},
|
||||||
|
|
||||||
"happy-alias": {
|
"happy-alias": {
|
||||||
cmd: "ctx ctx1",
|
cmd: "ctx ctx1",
|
||||||
ok: true,
|
ok: true,
|
||||||
ctx: "ctx1",
|
ctx: "ctx1",
|
||||||
},
|
},
|
||||||
|
|
||||||
"toast": {
|
"toast": {
|
||||||
cmd: "ctxto ctx1",
|
cmd: "ctxto ctx1",
|
||||||
},
|
},
|
||||||
|
|
||||||
"caps": {
|
"caps": {
|
||||||
cmd: "ctx Dev",
|
cmd: "ctx Dev",
|
||||||
ok: true,
|
ok: true,
|
||||||
ctx: "Dev",
|
ctx: "Dev",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"contains-key": {
|
||||||
|
cmd: "ctx kind-fred",
|
||||||
|
ok: true,
|
||||||
|
ctx: "kind-fred",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for k := range uu {
|
for k := range uu {
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,8 @@ const (
|
||||||
labelFlagEq = "="
|
labelFlagEq = "="
|
||||||
labelFlagEqs = "=="
|
labelFlagEqs = "=="
|
||||||
labelFlagNotEq = "!="
|
labelFlagNotEq = "!="
|
||||||
labelFlagIn = "in"
|
labelFlagIn = " in "
|
||||||
labelFlagNotin = "notin"
|
labelFlagNotin = " notin "
|
||||||
labelFlagQuote = "'"
|
labelFlagQuote = "'"
|
||||||
label
|
label
|
||||||
fuzzyFlag = "-f"
|
fuzzyFlag = "-f"
|
||||||
|
|
|
||||||
|
|
@ -215,7 +215,7 @@ func (c *Command) run(p *cmd.Interpreter, fqn string, clearStack, pushCmd bool)
|
||||||
co.SetFilter("", true)
|
co.SetFilter("", true)
|
||||||
co.SetLabelSelector(labels.Everything(), true)
|
co.SetLabelSelector(labels.Everything(), true)
|
||||||
if f, ok := p.FilterArg(); ok {
|
if f, ok := p.FilterArg(); ok {
|
||||||
co.SetFilter("/"+f, true)
|
co.SetFilter(f, true)
|
||||||
}
|
}
|
||||||
if f, ok := p.FuzzyArg(); ok {
|
if f, ok := p.FuzzyArg(); ok {
|
||||||
co.SetFilter("-f "+f, true)
|
co.SetFilter("-f "+f, 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"),
|
||||||
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"),
|
||||||
err: errors.New("blee"),
|
err: errors.New("blee"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -66,7 +66,7 @@ func Test_viewMetaFor(t *testing.T) {
|
||||||
}
|
}
|
||||||
c.alias.Define(client.PodGVR, "po", "pod", "pods", client.PodGVR.String())
|
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"), "pd")
|
||||||
c.alias.Define(client.NewGVR("pod @fred app=blee default"), "pdl")
|
c.alias.Define(client.NewGVR("pod @fred 'app=blee' default"), "pdl")
|
||||||
c.alias.Define(client.NewGVR("pdl"), "pdal")
|
c.alias.Define(client.NewGVR("pdl"), "pdal")
|
||||||
|
|
||||||
for k, u := range uu {
|
for k, u := range uu {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
name: k9s
|
name: k9s
|
||||||
base: core22
|
base: core22
|
||||||
version: 'v0.50.10'
|
version: 'v0.50.11'
|
||||||
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