diff --git a/Makefile b/Makefile
index 322022de..65011237 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
NAME := k9s
-VERSION ?= v0.50.10
+VERSION ?= v0.50.11
PACKAGE := github.com/derailed/$(NAME)
OUTPUT_BIN ?= execs/${NAME}
GO_FLAGS ?=
diff --git a/change_logs/release_v0.50.11.md b/change_logs/release_v0.50.11.md
new file mode 100644
index 00000000..a4e67790
--- /dev/null
+++ b/change_logs/release_v0.50.11.md
@@ -0,0 +1,30 @@
+
+
+# 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
+
+---
+
© 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/client/gvr.go b/internal/client/gvr.go
index c6d90bf6..9747494a 100644
--- a/internal/client/gvr.go
+++ b/internal/client/gvr.go
@@ -88,7 +88,7 @@ func (g *GVR) IsCommand() 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.
diff --git a/internal/config/alias_test.go b/internal/config/alias_test.go
index c49ddb39..afdeddca 100644
--- a/internal/config/alias_test.go
+++ b/internal/config/alias_test.go
@@ -201,14 +201,14 @@ func TestAliasResolve(t *testing.T) {
exp: "ppo",
ok: true,
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": {
exp: "ppc",
ok: true,
gvr: client.PodGVR,
- cmd: cmd.NewInterpreter("v1/pods @fred app=fred default"),
+ cmd: cmd.NewInterpreter("v1/pods @fred 'app=fred' default"),
},
"plain-filter": {
@@ -229,7 +229,21 @@ func TestAliasResolve(t *testing.T) {
exp: "ppc /fred @bozo ns-1",
ok: true,
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("pipo a=b,b=c default"), "ppo")
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 {
u := uu[k]
t.Run(k, func(t *testing.T) {
diff --git a/internal/view/cmd/args.go b/internal/view/cmd/args.go
index 478eb50f..cd53ad83 100644
--- a/internal/view/cmd/args.go
+++ b/internal/view/cmd/args.go
@@ -48,12 +48,12 @@ func newArgs(p *Interpreter, aa []string) args {
arguments[filterKey] = strings.ToLower(a[1:])
}
- case isLabelArg(a):
- arguments[labelKey] = strings.ToLower(a)
-
case strings.Index(a, contextFlag) == 0:
arguments[contextKey] = a[1:]
+ case isLabelArg(a):
+ arguments[labelKey] = strings.ToLower(a)
+
default:
switch {
case p.IsContextCmd():
@@ -86,6 +86,8 @@ func (a args) String() string {
for _, k := range slices.Sorted(kk) {
v := a[k]
switch k {
+ case labelKey:
+ v = "'" + v + "'"
case filterKey:
v = filterFlag + v
case contextKey:
diff --git a/internal/view/cmd/interpreter.go b/internal/view/cmd/interpreter.go
index 51be96b6..d0951043 100644
--- a/internal/view/cmd/interpreter.go
+++ b/internal/view/cmd/interpreter.go
@@ -52,9 +52,7 @@ func (c *Interpreter) Merge(p *Interpreter) {
}
c.cmd = p.cmd
for k, v := range p.args {
- // if _, ok := c.args[k]; !ok {
c.args[k] = v
- // }
}
c.line = c.cmd + " " + c.args.String()
}
diff --git a/internal/view/cmd/interpreter_test.go b/internal/view/cmd/interpreter_test.go
index 65b7e391..2cae281f 100644
--- a/internal/view/cmd/interpreter_test.go
+++ b/internal/view/cmd/interpreter_test.go
@@ -177,31 +177,42 @@ func TestFilterCmd(t *testing.T) {
filter string
}{
"empty": {},
+
"normal": {
cmd: "pod /fred",
ok: true,
filter: "fred",
},
+
"caps": {
cmd: "POD /FRED",
ok: true,
filter: "fred",
},
+
"filter+ns": {
cmd: "pod /fred ns1",
ok: true,
filter: "fred",
},
+
"ns+filter": {
cmd: "pod ns1 /fred",
ok: true,
filter: "fred",
},
+
"ns+filter+labels": {
cmd: "pod ns1 /fred app=blee,fred=zorg",
ok: true,
filter: "fred",
},
+
+ "filtered": {
+ cmd: "pod /cilium kube-system",
+ ok: true,
+ filter: "cilium",
+ },
}
for k := range uu {
@@ -431,24 +442,34 @@ func TestContextCmd(t *testing.T) {
ctx string
}{
"empty": {},
+
"happy-full": {
cmd: "context ctx1",
ok: true,
ctx: "ctx1",
},
+
"happy-alias": {
cmd: "ctx ctx1",
ok: true,
ctx: "ctx1",
},
+
"toast": {
cmd: "ctxto ctx1",
},
+
"caps": {
cmd: "ctx Dev",
ok: true,
ctx: "Dev",
},
+
+ "contains-key": {
+ cmd: "ctx kind-fred",
+ ok: true,
+ ctx: "kind-fred",
+ },
}
for k := range uu {
diff --git a/internal/view/cmd/types.go b/internal/view/cmd/types.go
index 052e2c92..0d2ea530 100644
--- a/internal/view/cmd/types.go
+++ b/internal/view/cmd/types.go
@@ -17,8 +17,8 @@ const (
labelFlagEq = "="
labelFlagEqs = "=="
labelFlagNotEq = "!="
- labelFlagIn = "in"
- labelFlagNotin = "notin"
+ labelFlagIn = " in "
+ labelFlagNotin = " notin "
labelFlagQuote = "'"
label
fuzzyFlag = "-f"
diff --git a/internal/view/command.go b/internal/view/command.go
index 2cfbaaad..bfe44d9d 100644
--- a/internal/view/command.go
+++ b/internal/view/command.go
@@ -215,7 +215,7 @@ func (c *Command) run(p *cmd.Interpreter, fqn string, clearStack, pushCmd bool)
co.SetFilter("", true)
co.SetLabelSelector(labels.Everything(), true)
if f, ok := p.FilterArg(); ok {
- co.SetFilter("/"+f, true)
+ co.SetFilter(f, true)
}
if f, ok := p.FuzzyArg(); ok {
co.SetFilter("-f "+f, true)
diff --git a/internal/view/command_test.go b/internal/view/command_test.go
index 5795cc67..b497859d 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"),
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"),
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.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")
for k, u := range uu {
diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml
index b62e1cab..96dc0f9c 100644
--- a/snap/snapcraft.yaml
+++ b/snap/snapcraft.yaml
@@ -1,6 +1,6 @@
name: k9s
base: core22
-version: 'v0.50.10'
+version: 'v0.50.11'
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.