diff --git a/Makefile b/Makefile
index 9154aba6..35cb6f91 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
NAME := k9s
-VERSION ?= v0.50.12
+VERSION ?= v0.50.13
PACKAGE := github.com/derailed/$(NAME)
OUTPUT_BIN ?= execs/${NAME}
GO_FLAGS ?=
diff --git a/change_logs/release_v0.50.13.md b/change_logs/release_v0.50.13.md
new file mode 100644
index 00000000..5efebf75
--- /dev/null
+++ b/change_logs/release_v0.50.13.md
@@ -0,0 +1,32 @@
+
+
+# Release v0.50.13
+
+## 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!
+
+## Resolved Issues
+
+* [#3587](https://github.com/derailed/k9s/issues/3587) UI doesn't show any updates when restarting a Deployment
+* [#3585](https://github.com/derailed/k9s/issues/3585) abbreviation sec for secret not working
+* [#3584](https://github.com/derailed/k9s/issues/3584) Show managed fields doesn't show them
+* [#3583](https://github.com/derailed/k9s/issues/3583) Cannot open shell to pods without node read access as of 0.50.12
+* [#3577](https://github.com/derailed/k9s/issues/3577) Log view is broken as of v0.50.10
+* [#3574](https://github.com/derailed/k9s/issues/3574) Aliases for pods with label filters not working
+
+---
+
© 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 9747494a..2e13f9e2 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, "/") && !strings.Contains(g.raw, " /")) || reservedGVRs.Has(g))
+ return g != nil && ((!strings.Contains(g.raw, " ") && 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.go b/internal/config/alias.go
index d64d3ba8..60c2d3f1 100644
--- a/internal/config/alias.go
+++ b/internal/config/alias.go
@@ -159,11 +159,15 @@ func (a *Aliases) LoadFile(path string) error {
}
a.mx.Lock()
- defer a.mx.Unlock()
if err := yaml.Unmarshal(bb, a); err != nil {
return err
}
+ for k, v := range a.Alias {
+ a.Alias[k] = client.NewGVR(v.String())
+ }
+ defer a.mx.Unlock()
+
return nil
}
diff --git a/internal/dao/helpers.go b/internal/dao/helpers.go
index 1d376b39..dcee0f46 100644
--- a/internal/dao/helpers.go
+++ b/internal/dao/helpers.go
@@ -8,7 +8,6 @@ import (
"errors"
"fmt"
"log/slog"
- "maps"
"math"
"github.com/derailed/k9s/internal/client"
@@ -95,17 +94,12 @@ func ToYAML(o runtime.Object, showManaged bool) (string, error) {
return "", fmt.Errorf("expecting unstructured object but got nil")
}
- mm := u.Object
- var (
- buff bytes.Buffer
- p printers.YAMLPrinter
- )
+ var p printers.ResourcePrinter = &printers.YAMLPrinter{}
if !showManaged {
- mm = maps.Clone(mm)
- if meta, ok := mm["metadata"].(map[string]any); ok {
- delete(meta, "managedFields")
- }
+ p = &printers.OmitManagedFieldsPrinter{Delegate: p}
}
+
+ var buff bytes.Buffer
if err := p.PrintObj(o, &buff); err != nil {
slog.Error("PrintObj failed", slogs.Error, err)
return "", err
diff --git a/internal/dao/pod.go b/internal/dao/pod.go
index 806cae3b..0b252ace 100644
--- a/internal/dao/pod.go
+++ b/internal/dao/pod.go
@@ -71,9 +71,9 @@ func (p *Pod) shouldStopRetrying(path string) bool {
switch pod.Status.Phase {
case v1.PodSucceeded, v1.PodFailed:
return true
+ default:
+ return false
}
-
- return false
}
// Get returns a resource instance if found, else an error.
diff --git a/internal/render/dp.go b/internal/render/dp.go
index ed6cdba0..f29dcdf9 100644
--- a/internal/render/dp.go
+++ b/internal/render/dp.go
@@ -100,7 +100,7 @@ func (d Deployment) defaultRow(raw *unstructured.Unstructured, r *model1.Row) er
strconv.Itoa(int(dp.Status.UpdatedReplicas)),
strconv.Itoa(int(dp.Status.AvailableReplicas)),
mapToStr(dp.Labels),
- AsStatus(d.diagnose(desired, dp.Status.AvailableReplicas)),
+ AsStatus(d.diagnose(dp.Status.Replicas, dp.Status.AvailableReplicas)),
ToAge(dp.GetCreationTimestamp()),
}
diff --git a/internal/render/sts.go b/internal/render/sts.go
index 4293ada2..c4fbf7ac 100644
--- a/internal/render/sts.go
+++ b/internal/render/sts.go
@@ -66,30 +66,34 @@ func (s StatefulSet) defaultRow(raw *unstructured.Unstructured, r *model1.Row) e
return err
}
+ var desired int32
+ if sts.Spec.Replicas != nil {
+ desired = *sts.Spec.Replicas
+ }
r.ID = client.MetaFQN(&sts.ObjectMeta)
r.Fields = model1.Fields{
sts.Namespace,
sts.Name,
computeVulScore(sts.Namespace, sts.Labels, &sts.Spec.Template.Spec),
- strconv.Itoa(int(sts.Status.ReadyReplicas)) + "/" + strconv.Itoa(int(sts.Status.Replicas)),
+ strconv.Itoa(int(sts.Status.ReadyReplicas)) + "/" + strconv.Itoa(int(desired)),
asSelector(sts.Spec.Selector),
na(sts.Spec.ServiceName),
podContainerNames(&sts.Spec.Template.Spec, true),
podImageNames(&sts.Spec.Template.Spec, true),
mapToStr(sts.Labels),
- AsStatus(s.diagnose(sts.Spec.Replicas, sts.Status.Replicas, sts.Status.ReadyReplicas)),
+ AsStatus(s.diagnose(desired, sts.Status.Replicas, sts.Status.ReadyReplicas)),
ToAge(sts.GetCreationTimestamp()),
}
return nil
}
-func (StatefulSet) diagnose(w *int32, d, r int32) error {
- if d != r {
- return fmt.Errorf("desired %d replicas got %d available", d, r)
+func (StatefulSet) diagnose(d, c, r int32) error {
+ if c != r {
+ return fmt.Errorf("desired %d replicas got %d available", c, r)
}
- if w != nil && *w != r {
- return fmt.Errorf("want %d replicas got %d available", *w, r)
+ if d != r {
+ return fmt.Errorf("want %d replicas got %d available", d, r)
}
return nil
diff --git a/internal/view/exec.go b/internal/view/exec.go
index 38eb60d0..236d94db 100644
--- a/internal/view/exec.go
+++ b/internal/view/exec.go
@@ -348,7 +348,7 @@ func sshIn(a *App, fqn, co string) error {
cfg := a.Config.K9s.ShellPod
platform, err := getPodOS(a.factory, fqn)
if err != nil {
- return fmt.Errorf("os detect failed: %w", err)
+ slog.Warn("os detect failed", slogs.Error, err)
}
args := buildShellArgs("exec", fqn, co, a.Conn().Config().Flags())
diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml
index 6154f8b1..2c091639 100644
--- a/snap/snapcraft.yaml
+++ b/snap/snapcraft.yaml
@@ -1,6 +1,6 @@
name: k9s
base: core22
-version: 'v0.50.12'
+version: 'v0.50.13'
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.