Rel v0.50.13 (#3592)
* fix #3587 - dp restart * fix #3585 - sec abreviation * fix #3583 - exec without node read * fix #3574 - label filter path * fix #3584 - managed fields * fix #3577 - pod logs * rel notesmine
parent
2ed7206896
commit
1d8cb6ced0
2
Makefile
2
Makefile
|
|
@ -1,5 +1,5 @@
|
||||||
NAME := k9s
|
NAME := k9s
|
||||||
VERSION ?= v0.50.12
|
VERSION ?= v0.50.13
|
||||||
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,32 @@
|
||||||
|
<img src="https://raw.githubusercontent.com/derailed/k9s/master/assets/k9s.png" align="center" width="800" height="auto"/>
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
---
|
||||||
|
<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, "/") && !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.
|
// WithSubResource builds a new gvr with a sub resource.
|
||||||
|
|
|
||||||
|
|
@ -159,11 +159,15 @@ func (a *Aliases) LoadFile(path string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
a.mx.Lock()
|
a.mx.Lock()
|
||||||
defer a.mx.Unlock()
|
|
||||||
if err := yaml.Unmarshal(bb, a); err != nil {
|
if err := yaml.Unmarshal(bb, a); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for k, v := range a.Alias {
|
||||||
|
a.Alias[k] = client.NewGVR(v.String())
|
||||||
|
}
|
||||||
|
defer a.mx.Unlock()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"maps"
|
|
||||||
"math"
|
"math"
|
||||||
|
|
||||||
"github.com/derailed/k9s/internal/client"
|
"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")
|
return "", fmt.Errorf("expecting unstructured object but got nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
mm := u.Object
|
var p printers.ResourcePrinter = &printers.YAMLPrinter{}
|
||||||
var (
|
|
||||||
buff bytes.Buffer
|
|
||||||
p printers.YAMLPrinter
|
|
||||||
)
|
|
||||||
if !showManaged {
|
if !showManaged {
|
||||||
mm = maps.Clone(mm)
|
p = &printers.OmitManagedFieldsPrinter{Delegate: p}
|
||||||
if meta, ok := mm["metadata"].(map[string]any); ok {
|
|
||||||
delete(meta, "managedFields")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var buff bytes.Buffer
|
||||||
if err := p.PrintObj(o, &buff); err != nil {
|
if err := p.PrintObj(o, &buff); err != nil {
|
||||||
slog.Error("PrintObj failed", slogs.Error, err)
|
slog.Error("PrintObj failed", slogs.Error, err)
|
||||||
return "", err
|
return "", err
|
||||||
|
|
|
||||||
|
|
@ -71,9 +71,9 @@ func (p *Pod) shouldStopRetrying(path string) bool {
|
||||||
switch pod.Status.Phase {
|
switch pod.Status.Phase {
|
||||||
case v1.PodSucceeded, v1.PodFailed:
|
case v1.PodSucceeded, v1.PodFailed:
|
||||||
return true
|
return true
|
||||||
}
|
default:
|
||||||
|
|
||||||
return false
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get returns a resource instance if found, else an error.
|
// Get returns a resource instance if found, else an error.
|
||||||
|
|
|
||||||
|
|
@ -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.UpdatedReplicas)),
|
||||||
strconv.Itoa(int(dp.Status.AvailableReplicas)),
|
strconv.Itoa(int(dp.Status.AvailableReplicas)),
|
||||||
mapToStr(dp.Labels),
|
mapToStr(dp.Labels),
|
||||||
AsStatus(d.diagnose(desired, dp.Status.AvailableReplicas)),
|
AsStatus(d.diagnose(dp.Status.Replicas, dp.Status.AvailableReplicas)),
|
||||||
ToAge(dp.GetCreationTimestamp()),
|
ToAge(dp.GetCreationTimestamp()),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -66,30 +66,34 @@ func (s StatefulSet) defaultRow(raw *unstructured.Unstructured, r *model1.Row) e
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var desired int32
|
||||||
|
if sts.Spec.Replicas != nil {
|
||||||
|
desired = *sts.Spec.Replicas
|
||||||
|
}
|
||||||
r.ID = client.MetaFQN(&sts.ObjectMeta)
|
r.ID = client.MetaFQN(&sts.ObjectMeta)
|
||||||
r.Fields = model1.Fields{
|
r.Fields = model1.Fields{
|
||||||
sts.Namespace,
|
sts.Namespace,
|
||||||
sts.Name,
|
sts.Name,
|
||||||
computeVulScore(sts.Namespace, sts.Labels, &sts.Spec.Template.Spec),
|
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),
|
asSelector(sts.Spec.Selector),
|
||||||
na(sts.Spec.ServiceName),
|
na(sts.Spec.ServiceName),
|
||||||
podContainerNames(&sts.Spec.Template.Spec, true),
|
podContainerNames(&sts.Spec.Template.Spec, true),
|
||||||
podImageNames(&sts.Spec.Template.Spec, true),
|
podImageNames(&sts.Spec.Template.Spec, true),
|
||||||
mapToStr(sts.Labels),
|
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()),
|
ToAge(sts.GetCreationTimestamp()),
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (StatefulSet) diagnose(w *int32, d, r int32) error {
|
func (StatefulSet) diagnose(d, c, r int32) error {
|
||||||
if d != r {
|
if c != r {
|
||||||
return fmt.Errorf("desired %d replicas got %d available", d, r)
|
return fmt.Errorf("desired %d replicas got %d available", c, r)
|
||||||
}
|
}
|
||||||
if w != nil && *w != r {
|
if d != r {
|
||||||
return fmt.Errorf("want %d replicas got %d available", *w, r)
|
return fmt.Errorf("want %d replicas got %d available", d, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -348,7 +348,7 @@ func sshIn(a *App, fqn, co string) error {
|
||||||
cfg := a.Config.K9s.ShellPod
|
cfg := a.Config.K9s.ShellPod
|
||||||
platform, err := getPodOS(a.factory, fqn)
|
platform, err := getPodOS(a.factory, fqn)
|
||||||
if err != nil {
|
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())
|
args := buildShellArgs("exec", fqn, co, a.Conn().Config().Flags())
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
name: k9s
|
name: k9s
|
||||||
base: core22
|
base: core22
|
||||||
version: 'v0.50.12'
|
version: 'v0.50.13'
|
||||||
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